Reputation: 621
I have a project based on the Angular 5.
Lets say that I have the two components: ParentComponent
and ChildComponent
. ChildComponent
has public setter with @Input()
decorator. I give to it property from the parent component that will be changed later.
My problem is - this setter doesn't work with Maps, Interfaces, Objects like
{ [ key: string ]: boolean }
only with Arrays and primitives.
Well, it works, but only once.
I already understand that it's something with the data type but who can give a good explanation or link to the docs? Didn't find the allowed data types on the Angular web-site with docs.
What's wrong here?
Link to plunker if someone needs: https://plnkr.co/edit/WBS55F3wZSYI0qGNEGSd?p=preview
As you can see, there are 3 setters, they work in the first time, then only Array and String setters work. Why?
Update: Looks like it works if I change in the Map some value by its key that already exists, but doesn't work if I add new key=>value pair.
Upvotes: 1
Views: 1203
Reputation: 62213
The fields mapItemsData
and arrayItemsData
are both only set one time. The field stringItemData
is set each time the object reference changes and this is because it is a string type and strings are immutable. The line this.stringItem += this.iterationValue.toString();
actually creates a new string reference each time it is called which causes the child component's setter to be called again with the new value.
The reason you do not see the data being updated for mapItemsData
is because you can't iterate it using *ngFor
but if you add this to your template you can see that the same object is updated
{{mapItems.size}}
If you wanted to iterate the Map
collection you can do that using entries().
<div *ngFor="let item of mapItems.entries()">{{ item }}</div>
For more information on the type Map see the documentation.
You also need to change your setting code so you do not point to a different (new) instance but point to the same instance that is being referenced in your parent (containing) component.
public set mapItemsData(set: Map<string, boolean>) {
// this.mapItems = []; <- you were changing the reference here
this.mapItems = set; // this is really all you need
}
Upvotes: 2