如何渲染实现接口的组件? [英] How can I render a component that implements an interface?

查看:96
本文介绍了如何渲染实现接口的组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个接口(或实际组件)ListItemRenderer和一个实现该接口(或扩展基本组件)的组件MyRendererComponent

Let's say I got an interface (or an actual component) ListItemRenderer and a component MyRendererComponent that implements that interface (or extends the base component)

@Component({
    selector: 'my-renderer',
    template: '<div>My renderer</div>'
})
export class MyRendererComponent implements ListItemRenderer {
    ...
}

我想将此具体实现传递给另一个组件,例如

I'd like to pass this concrete implementation to another component, e.g.

@Component({
    selector: 'my-list',
    template: `
        <ul [renderer]="renderer" [items]="items">
            <li *ngFor="let item of items">
                <!-- what goes here? -->
            </li>
        </ul>
    `
})
export class MyList {
    @Input() renderer: ListItemRenderer;
    @Input() items: any[];
    ...
}

很明显,父组件将具有类型为ListItemRenderer的公共属性renderer.问题是,我该如何在<li>中使用该组件(请参见上面的"这是怎么回事?")?

Obviously, the parent component would have a public property rendererof type ListItemRenderer. The question is, how do I go about using that component in my <li> (see "what goes here?" above)?

推荐答案

要使用*ngFor动态添加组件,您需要类似dcl-wrapper的内容,该内容在

To add components dynamically using *ngFor you need something like the dcl-wrapper explained in https://stackoverflow.com/a/36325468/217408 (DynamicComponentLoader is deprecated in favor of ViewContainerRef.createComponent() but I didn't try to introduce another name for the wrapper component.)

@Component({
  selector: '[dcl-wrapper]', // changed selector in order to be used with `<li>`
  template: `<div #target></div>`
})
export class DclWrapper {
  @ViewChild('target', {read: ViewContainerRef}) target;
  @Input() type;
  cmpRef:ComponentRef;
  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)
    });
  }

  ngOnChanges() {
    this.updateComponent();
  }

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

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

并像使用它

@Component({
    selector: 'my-list',
    template: `
        <ul  [items]="items">
            <li *ngFor="let item of items" dcl-wrapper [type]="renderer" ></li>
        </ul>
    `
})
export class MyList {
    @Input() renderer: ListItemRenderer;
    @Input() items: any[];
    ...
}

这篇关于如何渲染实现接口的组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆