The CollectionService
provides all the CRUD methods needed to interact with Firestore.
It simplifies the communication between your Akita and Firestore for a specific Collection.
Let's see how we can use it to connect MovieStore
with Firestore:
In your movie.store.ts, extend the MovieState
with CollectionState
:
export interface MovieState extends CollectionState<Movie> {}
Then in your movie.service.ts:
import { Injectable } from '@angular/core';
import { MovieStore, MovieState } from './movie.store';
import { CollectionConfig, CollectionService } from 'akita-ng-fire';
@Injectable({ providedIn: 'root' })
@CollectionConfig({ path: 'movies' })
export class MovieService extends CollectionService<MovieState> {
constructor(store: MovieStore) {
super(store);
}
}
Let's see what happen here:
- We create a
CollectionConfig
that hold the path to our collection in Firestore. - We extend our service with
CollectionService
. - We provide a
MovieState
inCollectionService
's generic.MovieState
has to extend theCollectionState
interface. - We pass
MovieStore
throughsuper()
.
In your component you can now start listening on Firebase:
@Component({
selector: 'app-root',
template: `
<ul>
<li *ngFor="let movie of movies$ | async">{{ movie.title }}</li>
<button (click)="add()">Add a Movie</button>
</ul>
`,
})
export class AppComponent implements OnInit, OnDestroy {
private subscription: Subscription;
public movies$: Observable<Movie[]>;
constructor(private service: MovieService, private query: MovieQuery) {}
ngOnInit() {
// Subscribe to the collection
this.subscription = this.service.syncCollection().subscribe();
// Get the list from the store
this.movies$ = this.query.selectAll();
}
// Add to Firestore's movie collection
add() {
this.service.add({ title: 'Star Wars' });
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Alternatively you can use a Guard to manage your subscriptions/unsubscriptions:
First create a new movie.guard.ts
:
@Injectable({ providedIn: 'root' })
export class MovieGuard extends CollectionGuard<Movie> {
constructor(service: MovieService) {
super(service);
}
}
In your movie.module.ts
@NgModule({
declarations: [HomeComponent, MovieListComponent],
imports: [
RouterModule.forChild([
{ path: '', component: HomeComponent },
{
path: 'movie-list',
component: MovieListComponent,
canActivate: [MovieGuard], // start sync (subscribe)
canDeactivate: [MovieGuard] // stop sync (unsubscribe)
}
])
]
})
export class MovieModule {}