【问题标题】:Angular 2 Passing data to component when dynamically adding the componentAngular 2动态添加组件时将数据传递给组件
【发布时间】:2017-01-07 16:45:23
【问题描述】:

我已经在点击按钮时动态添加了一个组件。

下面是我的小部件的代码。将颜色属性设置为输入的简单 div。

Widget.tmpl.html

 div class="{{color}}" (click)="ChangeColor()"

在 Widget 组件中,我将颜色作为输入。当我手动添加它时,这个组件工作正常。但是现在我正在尝试动态添加组件,并且还需要将颜色值传递给 Widget 组件。

下面是 app.component.ts 中的代码,我在点击按钮时调用 addItem()。

app.component.ts

export class AppComponent  {
  @ViewChild('placeholder', {read: ViewContainerRef}) viewContainerRef;
  private componentFactory: ComponentFactory<any>;

  constructor(componentFactoryResolver: ComponentFactoryResolver, compiler: Compiler) {
    this.componentFactory = componentFactoryResolver.resolveComponentFactory(MyAppComponent);

  }

  addItem () {
   this.viewContainerRef.createComponent(this.componentFactory, 0);
  }

 public  myValue:string = 'red';

 onChange(val: any) { this.myValue = val; } }

在 addItem() 方法中,我动态地将我的小部件组件添加到我的视图中。该组件被很好地添加。但问题是动态添加时如何传递颜色属性。根据我在创建小部件时传递的颜色,我希望它以红色或绿色等显示。如何在这种情况下进行属性绑定?

这里是一些代码:

export class MyAppComponent { 

    @Input() color; 
    @Output('changes') result: EventEmitter<any> = new EventEmitter(); 

    public constructor() { 
    }

    ChangeColor() {
        this.ToggleColor();
        this.result.emit(this.color);// Emitting the color to the parent.        
    }

    ToggleColor() {
        if (this.color == "red")
            this.color = "blue";
        else
            this.color = "red";
    }
}

在上面的代码中,我将颜色发送到父 app.component.ts,但由于我已经动态添加了小部件组件,所以我不知道在哪里添加此代码 (changes)="onChange($event)"。我尝试在 div 中添加此代码,如下所示:

<div class="{{color}}" (click)="ChangeColor()" (changes)="onChange($event)"></div>

但它不起作用。

【问题讨论】:

    标签: angular


    【解决方案1】:
    var cmpRef = this.viewContainerRef.createComponent(this.componentFactory, 0);
    cmpRef.instance.someProp = 'someValue';
    cmpRef.instance.someObservable.subscribe(val => this.someProp = val);
    

    【讨论】:

    • 当我尝试使用 @Output 从我的小部件组件发出事件时。它没有开火。我已将我的发射事件绑定到我的小部件的 div:
      下面是 widget.component.ts 的代码。
    • 你能编辑你的问题并在那里添加代码吗?上面的 HTML 在哪里?这是在动态添加组件的视图中吗?请添加更多代码以明确发生的情况。
    • 请编辑问题并在此处添加代码。 cmets 中的代码不可读。
    • (someEvent) 不监听任何事件。该事件必须由&lt;div&gt; 发出,但它是由AppComponent 发出的。 @Outputs() 发出的事件也不会冒泡。
    • 该数组是不必要的重复,因为 ViewContainerRef 维护 viewRef 的顺序。我在数组方法中看到的唯一价值是它更准确地读取长度,因为打印到 DOM 比推送到数组需要更多时间。刚刚提交github.com/angular/angular/issues/11223手指交叉。如果可以的话,请点赞。一如既往地感谢您的帮助 Günter
    【解决方案2】:

    如果你在 google https://netbasal.com/dynamically-creating-components-with-angular-a7346f4a982d 中找不到这篇文章,我会把它放在它上面,它完美地解释了如何传递数据,它对我理解 resolveComponentFactory 有很大帮助,对不起,答案更像是评论,但是我没有足够的声望。

    【讨论】:

    • 很高兴您链接了一篇文章,但是,链接不会永远存在。请将文章的相关部分粘贴到您的帖子中,以防链接失效。
    【解决方案3】:

    我也遇到过同样的问题:组件处理输入数据并根据这些数据创建自己的外观。唯一的问题是使用 html 模板(和预定义的输入数据)将组件添加为常规组件,并使用 componentFactory 动态添加组件,并在 ngInit 角度事件之后设置数据。由于在为组件设置输入数据之前触发了ngInit 事件,它破坏了所有初始化组件逻辑。一种可能的解决方案可能是基于允许初始化标志添加灵活的组件初始化,该标志在添加此组件之前和设置输入数据之后设置。

     initComponentData() {
            const canInitData = !this.appService.deniedInitData.value;
            if (canInitData) {
                this.initData();
            } else {
    
                this.subscriptions.push(
                    this.appService.deniedInitData.pipe(filter(x => !x),take(1)).subscribe(() => {
                        this.initData();
                    }));
            }
        }
    

    appService - 可注入的角度服务

    deniedInitData: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
    

    我们动态添加组件的地方:

    this.appService.deniedInitData.next(true);
    const cmpRef = this.viewContainerRef.createComponent(this.componentFactory, 0);
    
    const instance = cmpRef.instance;
    instance.someProp = 'someValue';                    
    this.appService.deniedInitData.next(false);
    

    【讨论】:

      猜你喜欢
      • 2017-06-15
      • 1970-01-01
      • 1970-01-01
      • 2017-08-30
      • 1970-01-01
      • 1970-01-01
      • 2021-04-12
      • 2020-05-26
      • 2017-08-29
      相关资源
      最近更新 更多