如何处理嵌套递归组件

时间:2017-02-14 08:58:35

标签: angular recursion angular2-template

我正在尝试构建一个树组件,其中od-tree-node组件以递归方式嵌套以构建子节点。我在处理事件时遇到问题。 对于叶节点上的单击事件,鼠标事件始终触发,就像事件发生在最顶层组件上一样。我不知道如何处理这个问题。

预期行为:当用户单击leaf / parent / root节点时,父组件(例如:app.component.ts)需要知道单击了哪个节点。

当前行为:无论单击哪个节点,都会选择根节点(发送到父组件)

plunker https://plnkr.co/edit/JZTlA5?p=preview

这是模板:

node.component.html

<!-- parent node -->
<label [attr.for]="resource.resourceType" [class]="cssClasses" *ngIf="resource.hasChildren()" [hidden]="matchedChildrenCount(search, resource) === 0">
     <a (click)="toggleNode($event)"> <i [class]="getNodeStateIcon()"></i></a>
     <input type="checkbox" *ngIf="showCheckboxes" [checked]="selected">
     <a [title]="resource.resourceName" (click)="selectNode($event);">
        <i [class]="resource.getIcon()"></i> {{resource.resourceName}} | {{ matchedChildrenCount(search, resource) | lpad : 2 : '0'}}
     </a>
</label>
<!-- leaf node -->
<label [attr.for]="resource.resourceType" [class]="cssClasses" *ngIf="!resource.hasChildren()" [hidden]="!isMatched(search, resource)">
     <input type="checkbox" *ngIf="showCheckboxes" [checked]="selected">
     <a [title]="resource.resourceName" (click)="selectNode($event);">
        <i class="icon-status-indicator"></i> {{resource.resourceName}}
        <div class="group" *ngIf="resource?.group !== 'Default'">{{resource.group}}</div>
     </a>
</label>
<!-- recrusive child nodes -->
<ul *ngIf="resource.expanded">
  <li *ngFor="let child of resource?.children">
    <od-tree-node
      [resource]="child"
      [search]="search"
      (selected)="selectNode($event)"
      ></od-tree-node>
  </li>
</ul>

node.component.ts

@Component({
    moduleId: module.id,
    selector: 'od-tree-node',
    templateUrl: 'node.component.html',
    styleUrls: ['node.component.css'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class NodeComponent implements OnInit, OnChanges, OnDestroy {
  @Input() resource: TreeNode;

  @Output() selected = new EventEmitter<TreeNode>();

  cssClasses: string;

  /**
   * select/unselect node
   *
   */
  selectNode(event: MouseEvent) {
    if(event instanceof MouseEvent) {
         event.preventDefault();
         event.stopPropagation();
      }
    this.resource.selected = true;
    this.cssClasses = this.setCssClasses();
    this.selected.emit(this.resource);
  }
 ...
 ....
 ....
}

1 个答案:

答案 0 :(得分:3)

在您的情况下,每个节点都将自己发送到其父节点,因此应用程序组件始终获取树的根节点。解决方案是在click事件的情况下将该节点本身发送到父节点,否则只传递从子节点的eventemitter接收的内容。

selectNode(event: MouseEvent) {
    console.log(event)
    let selNode: any;
    if(event instanceof MouseEvent) {
         event.preventDefault();
         event.stopPropagation();
         selNode = this.resource
    } else {
        selNode = event
    }
    this.selected.emit(selNode);
}