Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 递归组件数据引用问题_Angular - Fatal编程技术网

Angular 递归组件数据引用问题

Angular 递归组件数据引用问题,angular,Angular,我正在尝试构建一个类别选择器组件,该组件获得一个类别树作为第一手输入,如下所示: mockData: Category[] = [ { id: 1, name: 'main cat1', children: [ { id: 3, name: 'sub cat1', children: []}, { id: 4, name: 'sub kat2', children: []} ]}, { id: 2, name: 'main cat2', ch

我正在尝试构建一个类别选择器组件,该组件获得一个类别树作为第一手输入,如下所示:

 mockData: Category[] = [
    { id: 1, name: 'main cat1', children: [
       { id: 3, name: 'sub cat1', children: []},
       { id: 4, name: 'sub kat2', children: []}
    ]},
    { id: 2, name: 'main cat2', children: [
      { id: 5, name: 'sub cat5', children: []},
    ]},
  ]
模板: 该组件在
ngFor
中显示主要类别。如果选择了一个类别,它会手动将#tpl标记的模板插入到#vc视图容器中。这是对我的假设的一次尝试,我认为这会解决问题

<mat-chip-list aria-label="Category selection" [multiple]="false">
    <mat-chip *ngFor="let chip of data"
              [selected]="chip.id === selectedCategory?.id"
              (click)="clickChip($event, chip)">{{ chip.name }}</mat-chip>
</mat-chip-list>
<ng-container #vc></ng-container>


<ng-template #tpl>
  <span class="divider"> / </span>
  <category [data]="copyOFChildren"
            (selected)="emitSelected($event)"
  ></category>
</ng-template>

{{chip.name}
/ 
组成部分:

export class CategorySelectorComponent implements AfterViewInit, OnInit {

  @Input() data: Category[];
  @Output() selected: EventEmitter<Category> = new EventEmitter();

  selectedCategory: Category;
  copyOFChildren: Category[];

  @ViewChild("vc", {read: ViewContainerRef, static: true}) vc: ViewContainerRef;
  @ViewChild('tpl', {static:true}) tpl: TemplateRef<any>;
  childViewRef: ViewRef;

  ngAfterViewInit(){
    this.childViewRef = this.tpl.createEmbeddedView(null);
  }

  clickChip(event, category) {
    this.removeChildView();

    this.selectedCategory = (this.selectedCategory && this.selectedCategory.id === category.id) ? null : {...category};
    this.selected.emit(this.selectedCategory);
    this.insertChildView();
  }

  emitSelected(category: Category | null):void {
    if (category) {
      this.selected.emit(category)
    } else {
      this.selected.emit(this.selectedCategory)
    }
  }

  insertChildView(){
    if (this.selectedCategory && this.selectedCategory.children.length) {
      this.copyOFChildren = [ ...this.selectedCategory.children ];
      this.vc.insert(this.childViewRef);
    }
  }

  removeChildView(){
    this.copyOFChildren = undefined;
    this.vc.detach();
    console.log('detach')
  }
}

导出类CategorySelectorComponent在ViewInit、OnInit之后实现{
@输入()数据:类别[];
@选择输出():EventEmitter=新的EventEmitter();
selectedCategory:类别;
儿童:类别[];
@ViewChild(“vc”,{read:ViewContainerRef,static:true})vc:ViewContainerRef;

@ViewChild('tpl',{static:true})tpl:TemplateRef

同时找到了一个解决方案

问题是我使递归元素的组件保持活动状态,因此它保留在内存中,因为它在模板中的形式如下:

<ng-template #tpl>
  <span class="divider"> / </span>
  <category [data]="copyOFChildren"
            (selected)="emitSelected($event)"
  ></category>
</ng-template>

/ 
解决方案: 我没有使用
而是使用
ComponentFactoryResolver
手动创建子组件并将输入和输出绑定到它

查看演示: