Tom
Tom

Reputation: 4033

Only fetch data from Firestore once on app start, distribute it from there

So far I've used a mock containing an array from which the whole app got its data from, by iterating through it. Works fine.

export const CASES: Case[] = [
  { id: 0,
    name: 'Diesel',
    portfolioImage: '/assets/images/portfolio/diesel.png',
    image: '/assets/images/diesel.jpg',
    image2: '/assets/images/diesel/diesel-sunflower.png',
    image3: '/assets/images/diesel/diesel-cap.png',
    link: '/cases/diesel',
    header: 'black'
  },

  { id: 1,
    name: 'WeWork Berlin',
    portfolioImage: '/assets/images/portfolio/berlin.png',
    image: '/assets/images/berlin.jpg',
    image2: '/assets/images/wework/berlin-logo.png',
    image3: '/assets/images/wework/berlin-building.png',
    link: '/cases/wework',
    header: 'white'
  }
];

Currently I'm trying to connect my app to Firestore. To get data from Firestore I used the following code inside of my desired component:

export class PortfolioComponent implements OnInit {

  cases;

  constructor(private db: AngularFirestore) { }

  ngOnInit() {
    this.db.collection('entries').valueChanges()
      .subscribe(val => this.cases = val);
  }

}

It works, but I want to only call this once - to be exact is there a way to fetch the data on app init..

Doing so I want to achieve to only have to fetch the data once, insert it and distribute it from there. Just like I've done it without Firestore.

Upvotes: 0

Views: 276

Answers (1)

Nikola Stekovic
Nikola Stekovic

Reputation: 635

In order to fetch data on app init, you have to use APP_INITIALIZER which is an built in InjectionToken instance. Sample of app.module.ts would be:

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { AppInitService } from './app-init.service';

export function initializeApp1(appInitService: AppInitService) {
  return (): Promise<any> => { 
    return appInitService.Init();
  }
}

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [ 
    AppInitService,
    { provide: APP_INITIALIZER,useFactory: initializeApp1, deps: [AppInitService], multi: true}
  ],
})
export class AppModule { }

In your AppInitService you should make a request that will fetch data and you should keep it, if you're using NGRX in your store, if not, in some singleton root service. When you fetch data, you should return promise that will resolve.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AppInitService {

  // note dataSerice is service where you'll hold your data on fetch
  constructor(private db: AngularFirestore, private dataService: DataService) { }

  Init(): Promise<any> {
     return new Promise((resolve, reject) => {
this.db.collection('entries').valueChanges()
      .subscribe(val => {
         this.dataService.data = val; // assign data to data service
         resolve(true);
      });
     })
  }
}

Now, in this case, inject dataService: DataService anywhere you need and you'll have your data stored in data property.

Upvotes: 1

Related Questions