Querying is a killer feature of AngularFire2. You can specify query values as observables, and when those observables emit new values, the query is automatically re-run.
Queries are created by specifying a query
object on the FirebaseListObservable
options.
const queryObservable = af.database.list('/items', {
query: {
orderByChild: 'size',
equalTo: 'large'
}
});
Queries can only be ordered by one method. This means you can only specify
orderByChild
, orderByKey
, orderByPriority
, or orderByValue
.
// WARNING: Do not copy and paste. This will not work!
const queryObservable = af.database.list('/items', {
query: {
orderByChild: 'size',
equalTo: 'large',
orderByKey: true,
}
});
You can only use limitToFirst
or limitToLast
, but not both in combination.
// WARNING: Do not copy and paste. This will not work!
const queryObservable = af.database.list('/items', {
query: {
limitToFirst: 10,
limitToLast: 100,
}
});
Rather than specifying regular values, observables can be used to dynamically re-run queries when the observable emits a new value.
This is the magic of AngularFire2.
An RxJS Subject is imported below. A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners. See, What is a Subject for more information.
const subject = new Subject(); // import {Subject} from 'rxjs/Subject';
const queryObservable = af.database.list('/items', {
query: {
orderByChild: 'size',
equalTo: subject
}
});
// subscribe to changes
queryObservable.subscribe(queriedItems => {
console.log(queriedItems);
});
// trigger the query
subject.next('large');
// re-trigger the query!!!
subject.next('small');
Example app:
import { Component } from '@angular/core';
import { AngularFire, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2';
import { Subject } from 'rxjs/Subject';
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let item of items | async">
{{ item.text }}
</li>
</ul>
<div>
<h4>Filter by size</h4>
<button (click)="filterBy('small')">Small</button>
<button (click)="filterBy('medium')">Medium</button>
<button (click)="filterBy('large')">Large</button>
</div>
`,
})
export class AppComponent {
items: FirebaseListObservable<any[]>;
sizeSubject: Subject<any>;
constructor(af: AngularFire) {
this.sizeSubject = new Subject();
this.items = af.database.list('/items', {
query: {
orderByChild: 'size',
equalTo: this.sizeSubject
}
});
}
filterBy(size: string) {
this.sizeSubject.next(size);
}
}
+To run the above example as is, you need to have sample data in you firebase database with the following structure:"
-|items
-|item1
-|size: small
-|text: sample small text
-|item2
-|size: medium
-|text: sample medium text
-|item3
-|size: large
-|text: sample large text