是否可以在运行时动态设置组件@Input? [英] Is it possible to dynamically set a components @Input at run-time?

查看:83
本文介绍了是否可以在运行时动态设置组件@Input?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个dynamic-component-wrapper,它可以实例化传递给它的任何Component类.

Say I have a dynamic-component-wrapper that can instantiate any Component class that is passed into it.

// DRE013 DCOOKE 16/05/2017 - The component to instantiate.
@Input() componentType: Type<{}>;

// DRE013 DCOOKE 16/05/2017 - the component that will be created
private _cmpRef: ComponentRef<Component>;


// DRE013 DCOOKE 16/05/2017 - Creates a component ref in the view at #target
createComponent(){

    let factory = this.componentFactoryResolver.resolveComponentFactory(this.componentType);
    this._cmpRef = this.target.createComponent(factory);
    //this._cmpRef.instance.inputs >>>>>>>>> this is a string[] and I do not see how I can use this 
}

示例用法

<shared-dynamic-component [componentType]="TestComponent"></shared-dynamic-component>

哪里 TestComponent = TestComponent //class

这可以按预期工作,并且我可以像这样从dynamic-component-wrapper内部接收该组件的实例:

This works as expected, and I can receive an instance of this component from within the dynamic-component-wrapper like so:

this._cmpRef.instance

角度文档在此instance对象上不清楚-只是说明实例的类型为C-绝对没有引用C的实际含义.

The Angular docs are not clear on this instance object - simply stating that instance is of type C - with absolutely no reference to what C actually is.

非常感谢我的IDE告诉我:

Thankfully my IDE was able to tell me that :

ComponentRef.instance具有以下属性:

  • inputs : string[]
  • outputs : string[]
  • inputs : string[]
  • outputs : string[]

但是我不明白我将如何使用此信息.我以为这只是@Input字段的名称-但我不认为如何将复杂的对象作为输入传递.

However I do not understand how I am meant to use this information. I'd imagine this is just the names of the @Input fields - but I cannot think how I can pass in a complex object as an Input.

使用componentFactoryResolver动态创建组件后,是否可以设置@Inputs和其他元数据?

Is it possible for me to set the @Inputs and other meta-data after dynamically creating a component with the componentFactoryResolver?

推荐答案

自动更新

这似乎不可能.这是为什么的解释.

Automatic update

This doesn't seem to be possible. Here is the explanation why.

对于每个组件,Angular编译器都会创建一个工厂.您可以在ng://文件夹

For each component, Angular compiler creates a factory. You can observe all factories in the sources tab under ng:// folder, here is the example of how it looks. When it creates a factory, it defines nodes that will be rendered inside this component view. Some of the nodes are child components.

正是在生成该工厂时定义了框架应跟踪的输入属性.因此,除非您在编译之前定义了输入属性,否则Angular将不会跟踪和更新输入.

And it is at the time of generating this factory it is defined which input properties the framework should track. So unless you defined input properties before the compilation, Angular will not be tracking and updating the inputs.

以下是该工厂的外观示例:

Here is an example of how this factory looks like:

function View_AppComponent_0(l) {
  return jit_viewDef2(0,[
    jit_queryDef3(201326592,1,{someComp: 0}),
    (l()(),jit_elementDef4(0,null,null,1,'h1',[],null,null,null,null,null)),
    (l()(),jit_textDef5(null,[
      'Hello ',
      ''
    ]
    )),
    (l()(),jit_textDef5(null,['\n\n'])),
    (l()(),jit_elementDef4(0,null,null,1,'b-comp',[],null,null,null,jit_View_BComponent_06,jit__object_Object_7)),

      *************************************
      // this is a child component's node definition which has `some` property binding
      jit_directiveDef8(24576,null,0,jit_BComponent9,[],{some: [
        0,
        'some'  <------------------------ property name to track
      ]
    },null)
     **************************************************

  ]

使用this.componentFactoryResolver.resolveComponentFactory时,它实际上会搜索该工厂.它不会编译任何东西.

When you use this.componentFactoryResolver.resolveComponentFactory, it actually searches for that factory. It doesn't compile anything.

这肯定是可能的.您可以从父组件中查询子组件并更新属性-它会在子组件的模板中正确呈现.您甚至可以触发onChanges生命周期挂钩.

This certainly possible. You can query a child component from the parent component and update the property - it will be correctly rendered in the child component's template. And you can even trigger onChanges lifecycle hook.

export class AppComponent {
  @ViewChild(BComponent) bc;

  ngAfterViewInit() {
    setTimeout(() => {
      this.bc.some = 'foo';
      const changes = {some: new SimpleChange('', 'foo', true)};
      this.bc.ngOnChanges(changes);
    })
  }

这篇关于是否可以在运行时动态设置组件@Input?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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