【问题标题】:Angular2 pass directive in SubchildSubchild 中的 Angular2 传递指令
【发布时间】:2016-12-22 22:12:47
【问题描述】:

我构建了一个简单的 List UI 组件,其中包含项目,这些项目也是组件:

AppComponent -> ListComponent -> ListItemComponent

我希望这个列表能够可视化不同类型的列表项组件。

例如 2 种类型的列表项:

 @Component({
   selector: 'list-item',
   template: 'This is a PRODUCT!'
 })
 export class ProductListItemComponent { }
 @Component({
   selector: 'list-item',
   template: 'This is a PERSON!'
 })
 export class PersonListItemComponent { }

所以,当我初始化我的应用组件时:

 import {ListComponent} from '...';
 import {ProductListItemComponent} from '...';

 @Component({
   selector: 'list-item',
   template: `
     <list></list>
   `,
   directives: [
     ListComponent,
     ProductListItemComponent
   ]
 })
 export class AppComponent { }

它不起作用(当然),因为我的 ListComponent 没有从应用组件接收项目组件(指令)。

 @Component({
   selector: 'item',
   template: `
     <ul><li *ngFor=...>
       <list-item></list-item>
     </li></ul>
   `
 })
 export class ListComponent { }

我应该怎么做,如何让它工作? 提前谢谢!

【问题讨论】:

标签: angular angular2-directives


【解决方案1】:

首先 - 它是您的真实代码还是复制粘贴?因为我知道,几乎所有组件都有相同的选择器“列表项”,这是错误的。它应该是 uniq。

其次,关于问题本身 - 如果您希望它们在列表中呈现,您应该将 ProductListItemComponentPersonListItemComponent 直接添加到您的 ListComponent 中。像这样:

import {PersonListItemComponent} from '...';
import {ProductListItemComponent} from '...';

@Component({
 selector: 'list',
 template: `
   <ul><li *ngFor=...>
    <list-item></list-item>
   </li></ul>
 `,
 directives: [
   PersonListItemComponent,
   ProductListItemComponent
 ]
})
export class ListComponent { ...}

对于您的 AppComponent,您需要添加 for 'directives' prop only ListComponent

【讨论】:

  • 如果我确实喜欢你的例子,我应该给他们不同的选择器,但如果我动态传递组件而不是(我猜)它们可能是相同的。
  • 请检查我的解决方案。在最终版本中根本没有选择器!
【解决方案2】:

所以,这是我基于 Angular 2 dynamic tabs with user-click chosen components 构建的最终版本(谢谢 Gunter!)

解决方案是使用动态组件作为不同类型的 List 和 List Items 之间的中介。

import {
  Component, 
  ComponentFactory, 
  ComponentRef, 
  Input, 
  ViewContainerRef, 
  ComponentResolver, 
  ViewChild} from '@angular/core';

@Component({
  selector: 'dynamic-list-item',
  template: `<div #target></div>`
})
export class DynamicListItem {

  @ViewChild('target', {read: ViewContainerRef}) target;
  @Input() Type: any;
  @Input() Item: any;
  cmpRef: ComponentRef<any>;
  private isViewInitialized: boolean = false;

  constructor(private resolver: ComponentResolver) { }

  updateComponent() {
    if(!this.isViewInitialized) return;
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
    this.resolver.resolveComponent(this.Type).then((factory:ComponentFactory<any>) => {
      this.cmpRef = this.target.createComponent(factory);
      this.cmpRef.instance.Item = this.Item;
    });
  }

  ngOnChanges() {
    this.updateComponent();
  }

  ngAfterViewInit() {
    this.isViewInitialized = true;
    this.updateComponent();  
  }

  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }    
  }

}

Plunker example RC4

【讨论】:

    猜你喜欢
    • 2017-03-10
    • 2016-10-15
    • 2016-05-23
    • 1970-01-01
    • 2017-09-02
    • 2016-06-25
    • 2018-10-23
    • 2015-03-15
    • 1970-01-01
    相关资源
    最近更新 更多