Skip to content

Commit 60d153b

Browse files
authored
feat(afs): AngularFirestore
2 parents 689e987 + e7054df commit 60d153b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1772
-85
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@ npm-debug.log
99
angularfire2-*.tgz
1010
*.ngfactory.ts
1111
*.ngsummary.json
12+
.DS_Store
13+
yarn-error.log
1214
*.bak
1315
.DS_Store

CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Contributing to AngularFire2
1+
# Contributing to AngularFire
22

3-
We would love for you to contribute to AngularFire2 and help make it even better than it is
3+
We would love for you to contribute to AngularFire and help make it even better than it is
44
today! As a contributor, here are the guidelines we would like you to follow:
55

66
- [Code of Conduct](#coc)
@@ -50,7 +50,7 @@ and help you to craft the change so that it is successfully accepted into the pr
5050

5151
## <a name="setup"></a> Initial Setup
5252

53-
1) Create a fork of AngularFire2 (See [Forking a Project][github-fork])
53+
1) Create a fork of AngularFire (See [Forking a Project][github-fork])
5454

5555
2) CD into your clone and install dependencies
5656

README.md

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ Status: Release candidate
1010
## What is AngularFire?
1111

1212
- **Observable based** - Use the power of RxJS, Angular, and Firebase.
13-
- **Realtime bindings** - Synchronize data in reatime.
13+
- **Realtime bindings** - Synchronize data in realtime.
1414
- **Authentication** - Log users in with a variety of providers and monitor authentication state in realtime.
15+
- **Offline Data** - Store data offline automatically with AngularFirestore.
1516
- **ngrx friendly** - Integrate with ngrx using AngularFire's action based APIs.
1617

1718
#### Quick links
@@ -35,11 +36,11 @@ npm install firebase angularfire2@next --save
3536

3637
```ts
3738
import { Component } from '@angular/core';
38-
import { AngularFireDatabase } from 'angularfire2/database';
39+
import { AngularFirestore } from 'angularfire2/firestore';
3940
import { Observable } from 'rxjs/Observable';
4041

4142
@Component({
42-
selector: 'project-name-app',
43+
selector: 'app-root',
4344
template: `
4445
<ul>
4546
<li *ngFor="let item of items | async">
@@ -50,28 +51,49 @@ import { Observable } from 'rxjs/Observable';
5051
})
5152
export class MyApp {
5253
items: Observable<any[]>;
53-
constructor(db: AngularFireDatabase) {
54-
this.items = db.list('items').valueChanges();
54+
constructor(db: AngularFirestore) {
55+
this.items = db.collection('items').valueChanges();
5556
}
5657
}
5758
```
5859

5960
## Developer Guide
6061

6162
### Getting started
63+
6264
- [Installation & Setup](docs/1-install-and-setup.md)
6365

64-
### AngularFireDatabase
65-
- [Retrieving data as objects](docs/2-retrieving-data-as-objects.md)
66-
- [Retrieving data as lists](docs/3-retrieving-data-as-lists.md)
67-
- [Querying lists](docs/4-querying-lists.md)
66+
### Interacting with your database(s)
67+
68+
Firebase offers two cloud-based, client-accessible database solutions that support realtime data syncing. [Learn about the differences between them in the Firebase Documentation](https://firebase.google.com/docs/firestore/rtdb-vs-firestore).
69+
70+
#### Cloud Firestore
71+
72+
> `AngularFirestore` allows you to work with Cloud Firestore, the new flagship database for mobile app development. It improves on the successes of Realtime Database with a new, more intuitive data model. Cloud Firestore also features richer, faster queries and scales better than Realtime Database.
73+
74+
- [Documents](docs/firestore/documents.md)
75+
- [Collections](docs/firestore/collections.md)
76+
- [Querying Collections](docs/firestore/querying-collections.md)
77+
- [Offline data](docs/firestore/offline-data.md)
78+
79+
#### Realtime Database
6880

69-
### AngularFireAuth
70-
- [User Authentication](docs/5-user-authentication.md)
81+
> `AngularFireDatabase` allows you to work with the Realtime Database, Firebase's original database. It's an efficient, low-latency solution for mobile apps that require synced states across clients in realtime.
82+
83+
- [Objects](docs/rtdb/objects.md)
84+
- [Lists](docs/rtdb/lists.md)
85+
- [Querying lists](docs/rtdb/querying-lists.md)
86+
87+
### Authenticate users
88+
89+
- [Getting started with Firebase Authentication](docs/auth/getting-started.md)
7190

7291
### Deploy to Firebase Hosting
73-
- [Deploying AngularFire to Firebase Hosting](docs/7-deploying-angularfire-to-firebase.md)
92+
93+
- [Deploying AngularFire to Firebase Hosting](docs/deploying-angularfire-to-firebase.md)
7494

7595
### Ionic
76-
- [Using AngularFire with Ionic 2](docs/Auth-with-Ionic2.md)
77-
- [Using AngularFire with Ionic 3 and Angular 4](docs/Auth-with-Ionic3-Angular4.md)
96+
97+
- [Installation and Setup with Ionic CLI](docs/ionic/cli.md)
98+
- [Using AngularFire with Ionic 2](docs/ionic/v2.md)
99+
- [Using AngularFire with Ionic 3](docs/ionic/v3.md)

docs/5-user-authentication.md renamed to docs/auth/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 5. User authentication
1+
# 5. Getting started with Firebase Authentication
22

33
`AngularFireAuth.authState` provides you an `Observable<firebase.User>` to monitor your application's authentication State.
44

docs/7-deploying-angularfire-to-firebase.md renamed to docs/deploying-angularfire-to-firebase.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 7. Deploy AngularFire2 to Firebase
1+
# 7. Deploy AngularFire to Firebase
22

33
### 0. Build your Angular project for prod
44

docs/firestore/collections.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# 3. Collections in AngularFirestore
2+
3+
> Cloud Firestore is a NoSQL, document-oriented database. Unlike a SQL database, there are no tables or rows. Instead, you store data in *documents*, which are organized into *collections*.
4+
Each *document* contains a set of key-value pairs. Cloud Firestore is optimized for storing large collections of small documents.
5+
6+
## Using `AngularFirestoreCollection`
7+
8+
The `AngularFirestoreCollection` service is a wrapper around the native Firestore SDK's [`CollectionReference`](https://firebase.google.com/docs/reference/js/firebase.firestore.CollectionReference) and [`Query`](https://firebase.google.com/docs/reference/js/firebase.firestore.Query) types. It is a generic service that provides you with a strongly typed set of methods for manipulating and streaming data. This service is designed for use as an `@Injectable()`.
9+
10+
```ts
11+
import { Component } from '@angular/core';
12+
import { AngularFirestore, AngularFirestoreCollection } from 'angularfire2/firestore';
13+
import { Observable } from 'rxjs/Observable';
14+
15+
@Component({
16+
selector: 'app-root',
17+
template: `
18+
<ul>
19+
<li *ngFor="let item of items | async">
20+
{{ item.name }}
21+
</li>
22+
</ul>
23+
`
24+
})
25+
export class AppComponent {
26+
private itemsCollection: AngularFirestoreCollection<Item>;
27+
items: Observable<Item[]>;
28+
constructor(private afs: AngularFirestore) {
29+
this.itemsCollection = afs.collection<Item>('items');
30+
this.items = this.itemsCollection.valueChanges();
31+
}
32+
addItem(item: Item) {
33+
this.itemsCollection.add(item);
34+
}
35+
}
36+
```
37+
38+
The `AngularFirestoreCollection` is service you use to create streams of the collection and perform data operations on the underyling collection.
39+
40+
### The `DocumentChangeAction` type
41+
42+
With the exception of the `valueChanges()`, each streaming method returns an Observable of `DocumentChangeAction[]`.
43+
44+
A `DocumentChangeAction` gives you the `type` and `payload` properties. The `type` tells when what `DocumentChangeType` operation occured (`added`, `modified`, `removed`). The `payload` property is a `DocumentChange` which provides you important metdata about the change and a `doc` property which is the `DocumentSnapshot`.
45+
46+
```ts
47+
interface DocumentChangeAction {
48+
//'added' | 'modified' | 'removed';
49+
type: DocumentChangeType;
50+
payload: DocumentChange;
51+
}
52+
53+
interface DocumentChange {
54+
type: DocumentChangeType;
55+
doc: DocumentSnapshot;
56+
oldIndex: number;
57+
newIndex: number;
58+
}
59+
60+
interface DocumentSnapshot {
61+
exists: boolean;
62+
ref: DocumentReference;
63+
id: string;
64+
metadata: SnapshotMetadata;
65+
data(): DocumentData;
66+
get(fieldPath: string): any;
67+
}
68+
```
69+
70+
## Streaming collection data
71+
72+
There are multiple ways of streaming collection data from Firestore.
73+
74+
### `valueChanges()`
75+
**What is it?** - Returns an Observable of data as a synchronized array of JSON objects. All Snapshot metadata is stripped and just the method provides only the data.
76+
77+
**Why would you use it?** - When you just need a list of data. No document metadata is attached to the resulting array which makes it simple to render to a view.
78+
79+
**When would you not use it?** - When you need a more complex data structure than an array or you need the `id` of each document to use data manipulation metods. This method assumes you either are saving the `id` to the document data or using a "readonly" approach.
80+
81+
### `snapshotChanges()`
82+
**What is it?** - Returns an Observable of data as a synchronized array of `DocumentChangeAction[]`.
83+
84+
**Why would you use it?** - When you need a list of data but also want to keep around metadata. Metadata provides you the underyling `DocumentReference`, document id, and array index of the single document. Having the document's id around makes it easier to use data manipulation methods. This method gives you more horsepower with other Angular integrations such as ngrx, forms, and animations due to the `type` property. The `type` property on each `DocumentChangeAction` is useful for ngrx reducers, form states, and animation states.
85+
86+
**When would you not use it?** - When you need a more complex data structure than an array or if you need to process changes as they occur. This array is synchronized with the remote and local changes in Firestore.
87+
88+
### `stateChanges()`
89+
**What is it?** - Returns an Observable of the most recent changes as a `DocumentChangeAction[]`.
90+
91+
**Why would you use it?** - The above methods return a synchronized array sorted in query order. `stateChanges()` emits changes as they occur rather than syncing the query order. This works well for ngrx integrations as you can build your own data structure in your reducer methods.
92+
93+
**When would you not use it?** - When you just need a list of data. This is a more advanced usage of AngularFirestore.
94+
95+
### `auditTrail()`
96+
**What is it?** - Returns an Observable of `DocumentChangeAction[]` as they occur. Similar to `stateChanges()`, but instead it keeps around the trail of events as an array.
97+
98+
**Why would you use it?** - This method is like `stateChanges()` except it is not ephemeral. It collects each change in an array as they occur. This is useful for ngrx integrations where you need to replay the entire state of an application. This also works as a great debugging tool for all applications. You can simple write `afs.collection('items').auditTrail().subscribe(console.log)` and check the events in the console as they occur.
99+
100+
**When would you not use it?** - When you just need a list of data. This is a more advanced usage of AngularFirestore.
101+
102+
### Limiting events
103+
104+
There are three `DocumentChangeType`s in Firestore: `added`, `removed`, and `moved`. Each streaming method listens to all three by default. However, your site may only be intrested in one of these events. You can specify which events you'd like to use through the first parameter of each method:
105+
106+
#### Basic smaple
107+
```ts
108+
constructor(private afs: AngularFirestore): {
109+
this.itemsCollection = afs.collection<Item>('items');
110+
this.items = this.itemsCollection.snapshotChanges(['added', 'removed']);
111+
}
112+
```
113+
114+
#### Component Sample
115+
```ts
116+
import { Component } from '@angular/core';
117+
import { AngularFirestore, AngularFirestoreCollection } from 'angularfire2/firestore';
118+
import { Observable } from 'rxjs/Observable';
119+
120+
@Component({
121+
selector: 'app-root',
122+
template: `
123+
<ul>
124+
<li *ngFor="let item of items | async">
125+
{{ item.name }}
126+
</li>
127+
</ul>
128+
`
129+
})
130+
export class AppComponent {
131+
private itemsCollection: AngularFirestoreCollection<Item>;
132+
items: Observable<Item[]>;
133+
constructor(private afs: AngularFirestore) {
134+
this.itemsCollection = afs.collection<Item>('items');
135+
this.items = this.itemsCollection.valueChanges();
136+
}
137+
}
138+
```
139+
140+
## Adding documents to a collection
141+
142+
To add a new document to a collection with a generated id use the `add()` method. This method uses the type provided by the generic class to validate it's type structure.
143+
144+
#### Basic Sample
145+
```ts
146+
constructor(private afs: AngularFirestore): {
147+
const shirtsCollection = afs.collection<Item>('tshirts');
148+
shirtsCollection.add({ name: 'item', price: 10 });
149+
}
150+
```
151+
152+
## Manipulating individual documents
153+
154+
To retrieve, update, or delete an individual document you can use the `doc()` method. This method returns an `AngularFirestoreDocument`, which provides methods for streaming, updating, and deleting. [See Using Documents with AngularFirestore for more information on how to use documents](documents.md).
155+
156+
### [Next Step: Querying Collections in AngularFirestore](querying-collections.md)

docs/firestore/documents.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# 2. Documents in AngularFirestore
2+
3+
> Cloud Firestore is a NoSQL, document-oriented database. Unlike a SQL database, there are no tables or rows. Instead, you store data in *documents*, which are organized into *collections*.
4+
Each *document* contains a set of key-value pairs. Cloud Firestore is optimized for storing large collections of small documents.
5+
6+
## Using `AngularFirestoreDocument`
7+
8+
The `AngularFirestoreDocument` service is a wrapper around the native Firestore SDK's [`DocumentReference` type](https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference). It is a generic service that provides you with a strongly typed set of methods for manipulating and streaming data. This service is designed for use as an `@Injectable()`.
9+
10+
```ts
11+
import { Component } from '@angular/core';
12+
import { AngularFirestore, AngularFirestoreDocument } from 'angularfire2/firestore';
13+
import { Observable } from 'rxjs/Observable';
14+
15+
@Component({
16+
selector: 'app-root',
17+
template: `
18+
<div>
19+
{{ (item | async)?.name }}
20+
</div>
21+
`
22+
})
23+
export class AppComponent {
24+
private itemDoc: AngularFirestoreDocument<Item>;
25+
item: Observable<Item>;
26+
constructor(private afs: AngularFirestore) {
27+
this.itemDoc = afs.doc<Item>('items/1');
28+
this.item = this.itemDoc.valueChanges();
29+
}
30+
update(item: Item) {
31+
this.itemDoc.update(item);
32+
}
33+
}
34+
```
35+
36+
### The `DocumentChangeAction` type
37+
38+
With the exception of the `valueChanges()`, each streaming method returns an Observable of `DocumentChangeAction[]`.
39+
40+
A `DocumentChangeAction` gives you the `type` and `payload` properties. The `type` tells when what `DocumentChangeType` operation occured (`added`, `modified`, `removed`). The `payload` property is a `DocumentChange` which provides you important metdata about the change and a `doc` property which is the `DocumentSnapshot`.
41+
42+
```ts
43+
interface DocumentChangeAction {
44+
//'added' | 'modified' | 'removed';
45+
type: DocumentChangeType;
46+
payload: DocumentChange;
47+
}
48+
49+
interface DocumentChange {
50+
type: DocumentChangeType;
51+
doc: DocumentSnapshot;
52+
oldIndex: number;
53+
newIndex: number;
54+
}
55+
56+
interface DocumentSnapshot {
57+
exists: boolean;
58+
ref: DocumentReference;
59+
id: string;
60+
metadata: SnapshotMetadata;
61+
data(): DocumentData;
62+
get(fieldPath: string): any;
63+
}
64+
```
65+
66+
## Streaming document data
67+
68+
There are multiple ways of streaming collection data from Firestore.
69+
70+
### `valueChanges()`
71+
**What is it?** - Returns an Observable of document data. All Snapshot metadata is stripped and just the method provides only the data.
72+
73+
**Why would you use it?** - When you just need the object data. No document metadata is attached which makes it simple to render to a view.
74+
75+
**When would you not use it?** - When you need the `id` of the document to use data manipulation metods. This method assumes you either are saving the `id` to the document data or using a "readonly" approach.
76+
77+
### `snapshotChanges()`
78+
**What is it?** - Returns an Observable of data as a `DocumentChangeAction`.
79+
80+
**Why would you use it?** - When you need the document data but also want to keep around metadata. This metadata provides you the underyling `DocumentReference` and document id. Having the document's id around makes it easier to use data manipulation methods. This method gives you more horsepower with other Angular integrations such as ngrx, forms, and animations due to the `type` property. The `type` property on each `DocumentChangeAction` is useful for ngrx reducers, form states, and animation states.
81+
82+
**When would you not use it?** - When you simply need to render data to a view and don't want to do any extra processing.
83+
84+
## Manipulating documents
85+
86+
AngularFirestore provides methods for setting, updating, and deleting document data.
87+
88+
- `set(data: T)` - Destructively updates a document's data.
89+
- `update(data: T)` - Non-destructively updates a document's data.
90+
- `delete()` - Deletes an entire document. Does not delete any nested collections.
91+
92+
## Querying?
93+
94+
Querying has no effect on documents. Documents are a single object and querying effects a range of multiple documents. If you are looking for querying then you want to use a collection.
95+
96+
## Retrieving nested collections
97+
98+
Nesting collections is a great way to structure your data. This allows you to group related data structures together. If you are creating a "Task List" site, you can group "tasks" under a user: `user/<uid>/tasks`.
99+
100+
To retrieve a nested collection use the `collection(path: string)` method.
101+
102+
```ts
103+
constructor(private afs: AngularFirestore) {
104+
this.userDoc = afs.doc<Item>('user/david');
105+
this.tasks = this.userDoc.collection<Task>('tasks').valueChanges();
106+
}
107+
```
108+
109+
### [Next Step: Collections in AngularFirestore](collections.md)

0 commit comments

Comments
 (0)