We've been having some serious problems with the recent changes to how AngularFire treats objects/lists and referencing the objects throughout our app.
The primary thing is how the old AngularFireObject & AngularFireList
worked compared to the new ones. Our app was/is highly dependent on the $key
value as we denormalized extensively (as recommended).
Now the docs use a map example to get the $key
value but that isn't working the same, and even the valueChanges()
doesn't seem to work the same.
I'm not totally sure what we should do now with the changes.
Consider:
Old Way
/* /items/
a/{name: 'Dennis', city: 'Dallas'}
b/{name: 'Katie', city: 'Austin'}
c/{name: 'Will', city: 'Chicago'}
*/
let myAfList = this.af.list('path/to/items');
let itemsFirst, itemsSecond, itemsThird;
myAfList.subscribe(items => itemsFirst = items);
setTimeout(_ => myAfList.subscribe(items => itemsSecond = items), 1000);
setTimeout(_ => myAfList.subscribe(items => itemsThird = items), 2000);
/* Results for all three item arrays
itemsFirst: [
{name: 'Dennis', city: 'Dallas', $key: 'a'},
{name: 'Katie', city: 'Austin', $key: 'b'}
{name: 'Will', city: 'Chicago', $key: 'c'}
];
*/
All three subscriptions correctly get the full array of items and are setup to listen to future changes
New way with value changes:
let myAfList = this.af.list('path/to/items').valueChanges();
let itemsFirst, itemsSecond, itemsThird;
myAfList.subscribe(items => itemsFirst = items);
setTimeout(_ => myAfList.subscribe(items => itemsSecond = items), 1000);
setTimeout(_ => myAfList.subscribe(items => itemsThird = items), 2000);
/* Results for ONLY itemsFirst
itemsFirst: [
{name: 'Dennis', city: 'Dallas'},
{name: 'Katie', city: 'Austin'}
{name: 'Will', city: 'Chicago'}
];
*/
ItemsFirst
as the first subscription correctly gets the items. The other two items get nothing, but all three are subscribed for future changes. None have the key value.
With map for $key
let myAfList = this.af.list('path/to/items').snapshotChanges()
.map(actions => {
return actions.map(action => {
const $key = action.payload.key;
const data = { $key, ...action.payload.val() };
return data;
});
});
let itemsFirst, itemsSecond, itemsThird;
myAfList.subscribe(items => itemsFirst = items);
setTimeout(_ => myAfList.subscribe(items => itemsSecond = items), 1000);
setTimeout(_ => myAfList.subscribe(items => itemsThird = items), 2000);
/* Results for ONLY itemsFirst
itemsFirst: [
{name: 'Dennis', city: 'Dallas', $key: a},
{name: 'Katie', city: 'Austin', $key: b}
{name: 'Will', city: 'Chicago', $key: c}
];
*/
$key
is now on the list, but again it is only on the first item list...
So the quick observation is the objects now are really simple wrappers around core firebase references, and valueChanges() needs to be moved to the sub side like:
let myAfList = this.af.list('path/to/items');
myAfList.valueChanges().subscribe(items => itemsFirst = items);
This works! yay! But what about for the key? well there I have to write out the map function over and over. Or create my own function but it's not on the object proto so I have to add it to every file I use it in...
What am I missing? What is the correct way to get $key, have the subscriptions always get the full values?
Is there a better way to do this?