@FirebaseList and @FirebaseObject design
See original GitHub issueGoal: Have a declarative means of getting a Firebase reference into a component, to be used in a view.
Proposal:
@Component({
selector: 'posts-list',
changeDetection: ChangeDetectionStrategy. OnPush
template: `
<ul>
<li *ngFor="#post in posts | async">
{{post.val().title}}
<button (click)="posts.remove(post)">X</button>
</li>
</ul>
`
})
class PostsList {
@FirebaseList({
path: 'https://<FIREBASE>/posts' // Should eventually support relative to an injectable root.
}) posts:Observable<Post>;
The @FirebaseList decorator would create a subclassed Observable and set it to posts. The Observable would contain methods for updating the data. It’s generally considered bad practice to add non-combinator methods to an Observable, but there was no cleaner alternative that came to mind (I’m hoping for ideas!). Since the type is an Observable it can be unwrapped with the async pipe inside the template, and can take advantage of OnPush change detection to only perform dirty checking when a new array has been emitted from the Observable.
The FirebaseListObservable would support save, add, and remove similar to AngularFire, as well as lookup helpers to find items by key or find index of an item.
This design has the values inside the list as wrapped Firebase objects instead of POJS, which means .val() must be called inside the template. This is to make it easier to update data without having to reverse lookup records. There could be a pipe that would unwrap all objects, or developers could just map themselves:
<li *ngFor="#post in posts | af_unwrap | async">
class PostsList {
postsUnwrapped:Observable<Post>;
@FirebaseList(...) posts:Observable<Firebase>;
constructor() {
this.postsUnwrapped = this.posts.map(v => v.val());
}
}
This decorator is called @FirebaseList. There will be a separate decorator with similar semantics but for objects, called @FirebaseObject.
Querying
Query operators may optionally be supplied to the decorator:
@FirebaseList({
path: 'https://<FIREBASE>/posts',
query: [['orderByChild', 'timestamp'], ['limitToFirst', 2]]
})
Prior Art https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebasearray
The utilities used to make this functionality would carry over to the yet-to-be-designed Firebase pipe. The pipe would probably be the preferred tool for developers not familiar with, or able to use decorators.
I’ve got a branch with a functioning FirebaseList decorator that I’ll push soon.
Issue Analytics
- State:
- Created 8 years ago
- Comments:22 (11 by maintainers)

Top Related StackOverflow Question
Another thing I forgot to include in the proposal was how to manage pagination, or making the query more interactive. I want to make it possible to incorporate scalar or observable values into the
querypart of the list. And when new values would be pushed to an observable, the query would be re-performed underneath.Since the decorator definition object doesn’t have access to the class instance, it wouldn’t be possible to include direct references to class properties in the annotation. So there needs to be a way to reference the property by name instead of reference. The two ideas that come to mind are a string-based DSL to specify interpolated properties, i.e.
query: [['limitToFirst', '{{pageSize}}']]and a more explicit approach using functions to designate dynamic values:query: [['limitToFirst', observableQuery('pageSize')]]. I lean toward the 2nd, explicit option.Closing in favor of #39