Reputation: 678
I'm having troubles getting reactivity in the child components when i update the list in the parent component.
The data i have is pretty nested and looks like this
{ //projectList
"projects": [
{
"name": "project",
"displayed":true,
"layers": [
{
"name": "child_1",
"displayed":true
"layers": [
{
"name": "child_1_1",
"displayed":true
},
{
"name": "child_1_2",
"displayed":true
}
]
}
]
}
]
}
in the parent component I use *ngFor like this:
<li *ngFor="let project of projectList">
<child1
*ngIf="project.displayed"
[project]="project"
></child1>
</li>
the child1 component is also using another child2 in order to go deeper inn the structure if it contains more layers. So the child2 component uses recursion to create more levels, but i think the problems occurs way before that.
What I'm trying to do here is to filter the list and set displayed:false in the nested structure from the parent component. I want this change to get detected by child1 and child2, why doesnt it happen?
(the shown examples are simplified alot)
One solution to trigger changedetection is to do a projectList = copy(projectList) after i change the displayed attributes, but this introduces some unwanted behaviour
the filter function (simplified alot):
private setfilteredProjectList() { //STARTS HERE
this.projectList?.forEach((projectArray) => {
projectArray.layers.forEach((layer) => {
let filterSearch = this.filterSearchString(layer);
layer = filterSearch.layer;
});
});
}
private filterSearchString(layer: Layer) {
if (!layer.layers?.length) {
if (this.search === '') {
layer.displayed = true;
} else {
if (
layer.layername
.toLowerCase()
.startsWith(this.search.toLowerCase())
) {
layer.displayed = true;
} else {
layer.displayed = false;
}
}
} else {
layer.layers.map((l) => {
let childFiltered = this.filterSearchString(l);
return childFiltered.layer;
});
}
return { layer };
}
UPDATE: i see a great mistake i made; used forEach instead of map in setfilteredProjectList()...
Upvotes: 0
Views: 571
Reputation: 18849
This is an issue with reference
types (arrays and objects) where we have to change the location of RAM to ensure that change detection takes place and when you have nested objects and arrays, it becomes cumbersome and annoying but try this.
private setfilteredProjectList() { //STARTS HERE
// assign projectList to a new array
this.projectList = this.projectList?.map(project => { // the map in both cases
const layers = project.layers.map(layer => { // creates a new location in
let filterSearch = this.filterSearchString(layer); // memory and ensures
return filterSearch.layer; // change detection
}); // to take place
return {
...project, // spread the old project object
layers, // update the layers value
};
});
}
Upvotes: 2