Closed Maistho closed 3 years ago
i think you're looking for
this.list$ = this.db.list(ref).valueChanges(['child_added']).pipe(first());
@Kamshak Yes, that's what I'm using, but the bug is that limitToLast should already limit to only the most recently added item.
The following code will work, but is a workaround that I shouldn't need.
this.list$ = this.db.list(ref, ref => ref.limitToLast(1))
.valueChanges(['child_added'])
.pipe(first());
Limit to last will give you the last highest priority item (unless you order by child or something else) i think. It does not mean give me only last added child (1 value). See also https://firebase.google.com/docs/database/admin/retrieve-data#limit-queries
var ref = db.ref("dinosaurs");
ref.orderByChild("weight").limitToLast(2).on("child_added", function(snapshot) {
console.log(snapshot.key);
});
See the explanation:
The child_added callback is triggered exactly two times, unless there are less than two dinosaurs stored in the database. It will also get fired for every new, heavier dinosaur that gets added to the database
In your example the most recently added item changes once you add a new item, that's why it will emit a new one. Consider an app where you want to show the last user that signed up, you'd expect it to react if a new user is added.
Thanks for a good explanation! 👍
I still think that the behaviour is somewhat confusing though, since I get only the n
most recent values when not only listening to child_added
.
Maybe the Observable should not emit a list, and only emit values instead? I feel like my confusion is from getting a list with a bunch of child_added
events instead of getting each child one by one. When I've gotten the first child_added
event I will get that same event in the array every time a new child is added. 🤔
What I'm after in the end is to have an Observable that emits any new children in the list, and that only gives me the most recent child when starting the subscription. Probably easier to just not use angularfire in that case:
const subject = new ReplaySubject<any>(1)
const ref = this.db.database.ref('/dinosaurs');
ref.limitToLast(1).on('child_added', snapshot => {
this.ngZone.run(() => {
subject.next(snapshot.val());
});
});
Yeah you're right that might be a bug, it seems that in the implementation of the list observable it always merges in a "value" change [1], even though "child_added" would be enough to fetch everything. Perhaps there is a reason for this, @davideast probably knows more.
[1] See Line 10 here: https://github.com/angular/angularfire2/blob/2c2fe021667b8675a6ceabb891f979c20d632570/src/database/list/changes.ts#L9-L16
@Kamshak Child added is not enough to fetch everything. We need to know what the "initial state" of the list. That way we only emit the array once the "initial state" is in place.
closing as it seems this is working as intended for right now
Version info
Angular: 6.0.7
Firebase: 5.2.0
AngularFire: 5.0.0-rc.11
How to reproduce these conditions
Failing test unit, Plunkr, or JSFiddle demonstrating the problem
See this stackblitz
https://stackblitz.com/edit/angular-nm6r3a?file=app%2Fapp.component.ts
Steps to set up and reproduce
When using limitToLast and 'child_added' the limit is not kept after the first item.
Expected behavior
I should only get the latest added child
Actual behavior
I get every child that is added since I first started the subscription