Just need to start with a bit of app background (simplified)...
I have an existing Angular application that has just updates to lists of items received by polling a back end service.
For example, the following data containers...
class IdDescription {
public id: string
public description : string
}
class MyItem {
public prop1 : IdDescription;
public prop2 : IdDescription;
public prop3 : IdDescription;
// etc
}
class IncomingUpdates {
public updates: Array<MyItem>;
}
In my component I will have property to hold the array of items..
public data: Array<T>;
And in the markup I have the ngFor over the data
<div *ngFor="let item of data [@slideInOut]='slideInOutState' >
<div tappable (click)='clickItem(item)'>
<ion-ripple-effect></ion-ripple-effect>
<ion-grid>
<ion-row>
<ion-col class='card-main-data-col'>
<div <b>{{item.prop1.description}}</b></div>
<div [@valueUpdated]='item.prop2'>{{item.prop2.description}}</div>
<div [@valueUpdated]='item.prop3'>{{item.prop3.description}}</div>
</div>
</ion-col>
</ion-row>
</ion-grid>
</div>
When either prop2
or prop3
is updated, I have a trigger (valueUpdated
) to run a small animation...
trigger('valueUpdated', [
state('void => *', style({ transform: 'translate3d(0, 0, 0)' })),
state('* <=> *', style({ transform: 'translate3d(0, 0, 0)' })),
transition('void => *', []),
transition('* => void', []),
transition('* <=> *', [
animate(1000, style({ color: 'green', fontWeight: 'bold' }))
])
]),
So, the relevant part of, when these change I see them highlight bold and green.
Until now, when I have incoming data I have code to check the values, look for an existing MyItem
and then update any references to the IdDescription
property IF they have changed (ie I find by the id). So this has always worked, and I only see them change to green (the animation) when I update the reference to the property.
Now, I am wondering if I am doing too much, (ie all this checking), and if Angular can actually do most of this for my. Also, I am considering starting to use ngrx
, where the pattern is normally t change the whole reference to the list on any updates, and let Angular work out the DOM updates.
To test now I update the public data: Array<T>;
reference. Initially I could see (via the UI and via dev tools) that when I did this, the whole list DOM was being regenerated.
this.data = newState; // now replace reference
I then found I could add a trackBy to do the comparisons... ie
<div *ngFor="let item of daya;trackBy: trackByFunction"
with
public trackByFunction(index: number, item: MyItem) {
if (!item)
return null;
return item.prop1.code;
}
ie prop1
is the id of the whole item.
Now, from what I could see, the items where no longer being replaced in the DOM, exactly what I was after - so Angular is doing the compare and determining the data data was the same, so not updating the main items.
However, I DID still see the property animations firing, so I am assuming these "child" DOM elements wee still being replaced.
My question is, is there a way to also use some sort of "trackBy" for these "child" properties, so Angular knows they have the same values, and so does not update the DOM (and hence the animations do not fire)?