Angular 2:@ViewChildren用于递归组件

时间:2016-09-14 14:03:23

标签: recursion angular

我有一个递归组件,显示des tag a

首先,有父组件 - html

<div class=" suggestions" style="display : inline-block;" tabindex=-1 #autocompleteDiv>
     <span style="width: auto;cursor: pointer;position: absolue">
      <div *ngIf="hideInputField" style="border: 1px solid #9e9898">
          {{query}}
          <a style="color: #0012ff;" (click)="unselectData()">x </a>
      </div>
      <div *ngIf="!hideInputField">
        <input  type="text" [(ngModel)]="query"  (keyup)="handleKeyPress($event)" (keypress)="handleEnterPress($event)"
                style="padding: 4px;" (click)="displayDropdown();" #inputquery  (selectValueEvent)="select($event)">
        <div  #suggestion  *ngIf="divMustBeShow===true"  tabindex="-1">

          <div #recursivediv class="liclass" >
               <recursive-tree-view [treeNodeDisplay]="listToBuild"
                     [selectedItem]="selectedItem"
                     (selectValueEvent)="select($event)" #recursive></recursive-tree-view>
          </div>
        </div>
      </div>
  </span>
</div>

父代码(部分):

   displayDropdown() {
    if (this.divMustBeShow) {
        if ((this.query && this.query.length < 1) || !this.query) {
            this.divMustBeShow = false;
        }
    } else {
        this.divMustBeShow = true;

    }
}

handleEnterPress(key: KeyboardEvent) {

    if (key.keyCode === 13 || key.keyCode === 20) {
        //when press enter (13) or tab (20)
        this.query = this.recursive.selecItemWithEnterPress();
    }
}


handleKeyPress(key: KeyboardEvent) {
    if (key.key === "ArrowDown") {
        // if the pressed key is down arrow
        this.recursive.setDownListFocus()
    } else if (key.key === "ArrowUp") {
        // if the pressed key is up arrow
        this.recursive.setUpListFocus();
    } else if (key.keyCode === 13 || key.keyCode === 20) {
        //when press enter (13) or tab (20)
        this.query = this.recursive.selecItemWithEnterPress();
    } else if ((key.keyCode > 64 && key.keyCode < 91)   // key a -> z
        || key.keyCode === 32 // space
        || key.keyCode === 8 //  backspace
        || key.keyCode === 46 // delete
        || (key.keyCode > 47 && key.keyCode < 57) // 1-> 9
        || (key.keyCode > 95 && key.keyCode < 106))// 1-9 (numpad)
        if (this.query && this.query.length > 1) {
            this.divMustBeShow = true;
            this.listToBuild = this.filterFunction(this.query, this.originalMap, this.userLanguage);
        }
        else {
            this.divMustBeShow = true;
            this.listToBuild = this.filterFunction("", this.originalMap, this.userLanguage);
        }
}

组件递归树视图的html:

  <li *ngFor="let treeNode of treeNodeDisplay.getChildren(); let x = index;" style="cursor: default;">
     <div *ngIf="!treeNode.canBeClickable()">
          {{treeNode.getLabel()}}
      </div>
      <div *ngIf="treeNode.canBeClickable()">
      <a  #item (click)="select(treeNode.getId())" >
         {{treeNode.getLabel()}} </a>
       </div>
    <div *ngIf="nodeHasChildren(treeNode)">
         <recursive-tree-view [treeNodeDisplay]="treeNode"                       (selectValueEvent)="select($event)"  > </recursive-tree-view>
    </div>
  </li>
</ul>

在组件中,我希望拥有所有列表(因此是#item列表)

   @ViewChildren(forwardRef(() => "item"))
itemsList: QueryList<ElementRef>;
setDownListFocus() {
    if (this.lineCounter < this.itemsList.toArray().length) {

        if (this.lineCounter > 0) {  // one item is already selected
            //unselected previous element
            this._renderer.setElementStyle(this.itemsList.toArray()[this.lineCounter - 1].nativeElement, 'font-weight', 'normal');

        }
        this._renderer.setElementStyle(this.itemsList.toArray()[this.lineCounter].nativeElement, 'font-weight', 'bold');
        this.lineCounter++;
    }
}

setUpListFocus() {
    if (this.lineCounter > 0) {
        this.lineCounter--;
        this._renderer.setElementStyle(this.itemsList.toArray()[this.lineCounter - 1].nativeElement, 'font-weight', 'bold');
        this._renderer.setElementStyle(this.itemsList.toArray()[this.lineCounter].nativeElement, 'font-weight', 'normal');
    }

}

lineCounter在递归组件的ngOnInit中设置为1

显示结果为:

.....  (input text)
  node 1
     result1   => the first element must be in bold
     result2
  node2
     result3
     result4
     result5

当用户按下arrowDown键时,第一个元素(因此result1)必须具有font normal,而第二个元素(因此result2)必须以粗体显示 接下来,如果用户再次按下arrowDown键,则第二个元素(result2)必须正常,而hirs元素(结果3)必须为粗体 如果用户按下向上键,则第三个元素(result3)必须正常,第二个元素必须为粗体。

元素节点不能为粗体

1 个答案:

答案 0 :(得分:2)

@ViewChildren()仅适用于直接子女。

解决方法是共享服务,其中每个treeNode在创建时自我注册,并在ngOnDestroy中自行删除。

无法在treeNode上注册该服务,否则每个treeNode都会获得自己的实例。它必须是根节点或根模块的父节点。