angular / angularfire

Angular + Firebase = ❤️
https://firebaseopensource.com/projects/angular/angularfire2
MIT License
7.64k stars 2.2k forks source link

AngularFire does not work with MatTable animations #3130

Open mattpenner opened 2 years ago

mattpenner commented 2 years ago

Version info

Angular: 13.1.3

Firebase: 9.4.0

AngularFire: 7.1.2

Chrome: Version 97.0.4692.71 (Official Build) (64-bit)

Note: This is also the case with Angular 12.2.4, Angular/Fire 6.1.5 and Firebase 8.9.1

I have a MatTable that uses an observable collection as the datasource. I use a service that utilizes AngularFire to retrieve a Collection.ValueChanges() observable from Firestore. All works correctly for basic CRUD operations.

We are trying to add an animation to the table that helps identify objects that are added or removed from the table, similar to this example: https://stackblitz.com/edit/mat-table-animation-szynd2

I am triggering the animation based on :enter and :leave transitions.

This works perfectly fine when the source of the data in our tests is a local array or Observable such as in the Stackblitz example. However, when it is backed by an Observable collection filled by AngularFire the table goes through several refreshes. It's as if AngularFire is reloading the content with multiple objects and then filtering the collection. Here is what we are seeing: animation of refreshing table

I've tried about everything I can think of such as using a custom CDK DataSource collection object as in Angular's example, storing the AngularFire results into an array and pushing that to a local Observable used by MatTable, etc. For whatever reason anytime I use a data source other than AngularFire all works fine. But when I get the data from Firebase via AngularFire, no matter how I manipulate it, AngularFire does something strange to the collection causing the MatTable animation to trigger on multiple objects.

It appears that the array returned in the collection is somehow still being manipulated by AngularFire, with elements being added and removed until it's final state.

Unfortunately, I cannot find a way to create a Stackblitz that will successfully use Firestore.

How to reproduce these conditions

Create a new Angular project with Material, Firebase and Angular Fire. Create a Mat-Table that uses an Angular Fire streaming Collection (i.e. Collection.ValueChanges()) as its data source. Add and remove items from the firestore collection triggering an update to the table's data source.

google-oss-bot commented 2 years ago

This issue does not seem to follow the issue template. Make sure you provide all the required information.

mattpenner commented 2 years ago

I believe this might be an issue that in the updated collection the same items are not referentially equal to the same items in the prior collection. Meaning, even though the entities are the same records (values) the new collection are different objects, so MatTable believes the entire collection are new items.

This will require some research to determine if, indeed, the items in the classic local Observable test are referentially equal and if the items from the AngularFire stream are referentially equal. If the later is not true then it's a question of whether subsequent streams can be referentially equal (ability to use Immer?), if MatTable datasource/animations can be somehow triggered on some other ability to detect new/same items, or perhaps a proxy needs to sit between AngularFire's collection and MatTable, which can handle the referential integrity issue itself.