akita-ng-fire simplifies the connection between Akita and Firebase inside an Angular project.
ng add @angular/firenpm install akita-ng-fire
First, create a new entity feature with Akita :
ng g feature movies/movie
In your movie.store.ts
, extend the MovieState
with CollectionState
:
export interface MovieState extends CollectionState<Movie> {}
Then in your movie.service.ts
add the following code:
import { Injectable } from '@angular/core';import { MovieStore, MovieState } from './movie.store';import { AngularFirestore } from '@angular/fire/firestore';import { CollectionConfig, CollectionService } from 'akita-ng-fire';@Injectable({ providedIn: 'root' })@CollectionConfig({ path: 'movies' })export class MovieService extends CollectionService<MovieState> {constructor(store: MovieStore) {super(store);}}
The CollectionConfig
decorator takes the path to our collection in Firestore
. We extend the CollectionService
passing a reference to the Firestore
database and our store.
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 sub: Subscription;public movies$: Observable<Movie[]>;constructor(private service: MovieService,private query: MovieQuery) {}ngOnInit() {// Subscribe to the collectionthis.sub = this.service.syncCollection().subscribe();// Get the list from the storethis.movies$ = this.query.selectAll();}ngOnDestroy() {this.sub.unsubscribe();}// Add to Firestore's movie collectionadd() {this.service.add({ title: 'Star Wars' });}}
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<MovieState> {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 {}