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

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

问题描述

假设我有一个接口(或一个实际组件)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.问题是,如何在我的

  • 中使用该组件(请参阅上面的这里有什么?")?

    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-wrapperhref="https://stackoverflow.com/a/36325468/217408">https://stackoverflow.com/a/36325468/217408(DynamicComponentLoader 已弃用,支持 ViewContainerRef.createComponent() 但我没有尝试为包装器组件引入另一个名称.)

    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天全站免登陆