在Angular中,动态创建的子组件不会更新其@Input。

huangapple go评论83阅读模式
英文:

In Angular Child created dynamically don't get their @Input updated

问题

I have created a simple demo of my issue HERE.

So I have a parent which have a topics list (just an array of string), this topics list is generated randomly each time we click on the button generate (button which is in the parent)

Then I have a component named child which takes as input the topics list and a title.

When I create this child through the DOM it works as expected. But when I create the exact same child component but programmatically then the topics list is not updated.

So when I create this child through the DOM like this:

<app-child [topicsList]="topicsList" [title]="'Child created from the DOM'"></app-child>

It is working as expected, when I click on generate, the child get the updated topics list and display it. But when I create the exact same child component but programmatically like this:

this.mChildRef = this.mViewContainerRef.createComponent(ChildComponent); this.mChildRef.setInput('topicsList', this.topicsList); this.mChildRef.setInput('title', "Child created dynamically");

then the topics list is not updated. I tried with public variables instead of @Input and set the Inputs like this: this.mChildRef.instance.topicsList = this.topicsList I also tried to play with: this.mChildRef.changeDetectorRef I try to get changes through ngOnChanges but this event is fired only at the creation of the child component.

But nothing works...

enter image description here

I have probably missed something but I don't know what, maybe a specific configuration in the component or an extra parameter to pass when I create the component.

Thank you for your help 在Angular中,动态创建的子组件不会更新其@Input。

英文:

I have created a simple demo of my issue HERE.

So I have a parent which have a topics list (just an array of string), this topics list is generated randomly each time we click on the button generate (button which is in the parent)

Then I have a component named child which takes as input the topics list and a title.

When I create this child through the DOM it works as expected. But when I create the exact same child component but programmatically then the topics list is not updated.

So when I create this child through the DOM like this:

<app-child [topicsList]="topicsList" [title]="'Child created from the DOM'"></app-child>

It is working as expected, when I click on generate, the child get the updated topics list and display it. But when I create the exact same child component but programmatically like this:

this.mChildRef = this.mViewContainerRef.createComponent(ChildComponent);
this.mChildRef.setInput('topicsList', this.topicsList);
this.mChildRef.setInput('title', "Child created dynamically");

then the topics list is not updated.
I tried with public variables instead of @Input and set the Inputs like this:
this.mChildRef.instance.topicsList = this.topicsList
I also tried to play with:
this.mChildRef.changeDetectorRef
I try to get changes through ngOnChanges but this event is fired only at the creation of the child component.

But nothing works...

enter image description here

I have probably missed something but I don't know what, maybe a specific configuration in the component or an extra parameter to pass when I create the component.

Thank you for your help 在Angular中,动态创建的子组件不会更新其@Input。

答案1

得分: 1

以下是用于Stack Overflow的答案:

// 创建一个动态子组件的映射
private childComponentsMap: Map<string, ComponentRef<ChildComponent>> = new Map();

// 将子组件添加到映射中
this.childComponentsMap.set('Id' + this.componentId, this.mChildRef);

// 遍历子组件映射并更新主题列表
this.childComponentsMap.forEach((componentRef) => {
  componentRef.instance.topicsList = this.topicsList;
});

在提供的代码片段中,childComponentsMap 被创建为一个 Map,用于存储动态创建的子组件。每个组件都以唯一的标识符('Id' + this.componentId)作为键,相应的 ComponentRef<ChildComponent> 作为值添加到映射中。

要更新所有子组件的主题列表,您可以使用 forEach 方法遍历 childComponentsMap。在循环内,您可以访问每个组件引用(componentRef)并将其 topicsList 属性设置为更新后的 this.topicsList 值。

这种方法允许您维护一个动态创建的子组件的映射,并根据需要轻松更新它们的属性。

希望这有助于解决您的问题。如果您有任何进一步的问题,请随时告诉我!

英文:

Below is the answer you can use for Stack Overflow:

// Create a map of dynamic child components
private childComponentsMap: Map<string, ComponentRef<ChildComponent>> = new Map();

// Add child component to the map
this.childComponentsMap.set('Id' + this.componentId, this.mChildRef);

// Iterate through the child components map and update the topics list
this.childComponentsMap.forEach((componentRef) => {
  componentRef.instance.topicsList = this.topicsList;
});

In the provided code snippet, the childComponentsMap is created as a Map to store the dynamically created child components. Each component is added to the map using a unique identifier ('Id' + this.componentId) as the key and the corresponding ComponentRef<ChildComponent> as the value.

To update the topics list for all the child components, you can iterate through the childComponentsMap using the forEach method. Within the loop, you can access each component reference (componentRef) and set its topicsList property to the updated this.topicsList value.

This approach allows you to maintain a map of dynamically created child components and easily update their properties as needed.

I hope this helps to resolve your issue. Let me know if you have any further questions!

答案2

得分: 0

你必须明确更新输入,如果组件是动态创建的。

// 列表更新后
this.mChildRef.setInput('topicsList', this.topicsList);

你也可以做一些巧妙的事情,比如将元素置于原始列表中,该列表已绑定到组件的输入。

this.topicsList.splice(0, 999, ...topicsList);

但要自担风险,因为这可能会导致难以调试的错误,并且不适用于 OnPush 策略。

英文:

you have to explicitly update the input if the component was created dynamically

// after list update
this.mChildRef.setInput('topicsList', this.topicsList);

you could also do something tricky like emplacing elements in the original list that was bound to component input

this.topicsList.splice(0, 999, ...topicsList);

but do it at your risk, because it can cause bugs that are hard to debug and it won't work with OnPush strategy

答案3

得分: 0

If I've right understood, you need to update onGenerateTopicsList method:

onGenerateTopicsList(): void {
// your existing code...
this.mChildRef.setInput('topicsList', this.topicsList);
}

英文:

If I've right understood, you need to update onGenerateTopicsList method:

onGenerateTopicsList(): void {
  // your existing code...  
  this.mChildRef.setInput('topicsList', this.topicsList);   
}

huangapple
  • 本文由 发表于 2023年6月26日 18:26:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76555804.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定