Skip to content

Commit ac0787b

Browse files
jamesdanielsdavideast
authored andcommitted
docs(db): updating the querying docs for the new API (#1170)
* docs(db): updating the querying docs for the new API * docs(db): cleanup some of the formatting * docs(db): kill unneeded quote character * docs(db): adding a clear filter + show all results first * docs(db): allow null in the filterBy example
1 parent f277779 commit ac0787b

File tree

1 file changed

+54
-61
lines changed

1 file changed

+54
-61
lines changed

docs/4-querying-lists.md

Lines changed: 54 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
# 4. Querying lists
22

3-
> Querying is a killer feature of AngularFire2.
4-
You can specify query values as observables, and when those
5-
observables emit new values, the query is automatically re-run.
3+
> Querying is a killer feature of AngularFire2.
64
75
## Creating a query with primitive/scalar values
86

9-
Queries are created by specifying a `query` object on the `FirebaseListObservable` options.
7+
Queries are created by building on the [`firebase.database.Reference`](https://firebase.google.com/docs/reference/js/firebase.database.Reference).
108

119
```ts
12-
const queryObservable = db.list('/items', {
13-
query: {
14-
orderByChild: 'size',
15-
equalTo: 'large'
16-
}
17-
});
10+
db.list('/items', ref => ref.orderByChild('size').equalTo('large'))
1811
```
1912

2013
**Query Options:**
@@ -35,70 +28,62 @@ const queryObservable = db.list('/items', {
3528

3629
<sup>2</sup> The Firebase SDK supports an optional `key` parameter for [`startAt`](https://firebase.google.com/docs/reference/js/firebase.database.Reference#startAt), [`endAt`](https://firebase.google.com/docs/reference/js/firebase.database.Reference#endAt), and [`equalTo`](https://firebase.google.com/docs/reference/js/firebase.database.Reference#equalTo) when ordering by child, value, or priority. You can specify the `key` parameter using an object literal that contains the `value` and the `key`. For example: `startAt: { value: 'some-value', key: 'some-key' }`.
3730

31+
To learn more about how sorting and ordering data works in Firebase, check out the Firebase documentation on [working with lists of data](https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data).
32+
3833
## Invalid query combinations
3934

4035
**Queries can only be ordered by one method.** This means you can only specify
4136
`orderByChild`, `orderByKey`, `orderByPriority`, or `orderByValue`.
4237

4338
```ts
4439
// WARNING: Do not copy and paste. This will not work!
45-
const queryObservable = db.list('/items', {
46-
query: {
47-
orderByChild: 'size',
48-
equalTo: 'large',
49-
orderByKey: true,
50-
}
51-
});
40+
ref.orderByChild('size').equalTo('large').orderByKey(true)
5241
```
5342

5443
You can only use `limitToFirst` or `limitToLast`, but not both in combination.
5544

5645
```ts
5746
// WARNING: Do not copy and paste. This will not work!
58-
const queryObservable = db.list('/items', {
59-
query: {
60-
limitToFirst: 10,
61-
limitToLast: 100,
62-
}
63-
});
47+
ref.limitToFirst(10).limitToLast(100)
6448
```
6549

6650
## Creating a query with observable values
6751

68-
Rather than specifying regular values, observables can be used to dynamically
69-
re-run queries when the observable emits a new value.
70-
71-
This is the magic of AngularFire2.
52+
To enable dynamic queries one should lean on RxJS Operators like `switchMap`.
7253

7354
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](http://reactivex.io/rxjs/manual/overview.html#subject) for more information.
7455

56+
When we call [`switchMap` on the Subject](https://www.learnrxjs.io/operators/transformation/switchmap.html), we cap map each value to a new Observable; in this case a database query.
57+
7558
```ts
76-
const subject = new Subject(); // import {Subject} from 'rxjs/Subject';
77-
const queryObservable = db.list('/items', {
78-
query: {
79-
orderByChild: 'size',
80-
equalTo: subject
81-
}
82-
});
59+
const size$ = new Subject<string>();
60+
const queryObservable = size$.switchMap(size =>
61+
db.list('/items', ref => ref.orderByChild('size').equalTo(size)).valueChanges();
62+
);
8363

8464
// subscribe to changes
8565
queryObservable.subscribe(queriedItems => {
8666
console.log(queriedItems);
8767
});
8868

8969
// trigger the query
90-
subject.next('large');
70+
size$.next('large');
9171

9272
// re-trigger the query!!!
93-
subject.next('small');
73+
size$.next('small');
9474
```
9575

9676
**Example app:**
77+
78+
[See this example in action on StackBlitz](https://stackblitz.com/edit/angularfire-db-api-s8ip7m).
9779

9880
```ts
9981
import { Component } from '@angular/core';
100-
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';
101-
import { Subject } from 'rxjs/Subject';
82+
import { AngularFireDatabase, AngularFireAction } from 'angularfire2/database';
83+
import { Observable } from 'rxjs/Observable';
84+
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
85+
import { Subscription } from 'rxjs/Subscription';
86+
import 'rxjs/add/operator/switchMap';
10287

10388
@Component({
10489
selector: 'app-root',
@@ -113,41 +98,49 @@ import { Subject } from 'rxjs/Subject';
11398
<button (click)="filterBy('small')">Small</button>
11499
<button (click)="filterBy('medium')">Medium</button>
115100
<button (click)="filterBy('large')">Large</button>
101+
<button (click)="filterBy(null)" *ngIf="this.size$.getValue()">
102+
<em>clear filter</em>
103+
</button>
116104
</div>
117105
`,
118106
})
119107
export class AppComponent {
120-
items: FirebaseListObservable<any[]>;
121-
sizeSubject: Subject<any>;
108+
items: Observable<AngularFireAction<firebase.database.DataSnapshot>[]>;
109+
size$: BehaviorSubject<string|null>;
122110

123111
constructor(db: AngularFireDatabase) {
124-
this.sizeSubject = new Subject();
125-
this.items = db.list('/items', {
126-
query: {
127-
orderByChild: 'size',
128-
equalTo: this.sizeSubject
129-
}
130-
});
112+
this.size$ = new BehaviorSubject(null);
113+
this.items = this.size$.switchMap(size =>
114+
db.list('/items', ref =>
115+
size ? ref.orderByChild('size').equalTo(size) : ref
116+
).valueChanges();
117+
);
131118
}
132-
filterBy(size: string) {
133-
this.sizeSubject.next(size);
119+
filterBy(size: string|null) {
120+
this.size$.next(size);
134121
}
135122
}
136123
```
137124

138-
+**To run the above example as is, you need to have sample data in you firebase database with the following structure:"**
125+
**To run the above example as is, you need to have sample data in you firebase database with the following structure:**
139126

140-
```ts
141-
-|items
142-
-|item1
143-
-|size: small
144-
-|text: sample small text
145-
-|item2
146-
-|size: medium
147-
-|text: sample medium text
148-
-|item3
149-
-|size: large
150-
-|text: sample large text
127+
```json
128+
{
129+
"items": {
130+
"a" : {
131+
"size" : "small",
132+
"text" : "small thing"
133+
},
134+
"b" : {
135+
"size" : "medium",
136+
"text" : "medium sample"
137+
},
138+
"c" : {
139+
"size" : "large",
140+
"text" : "large widget"
141+
}
142+
}
143+
}
151144
```
152145

153146
### [Next Step: User Authentication](5-user-authentication.md)

0 commit comments

Comments
 (0)