I want to make an API call by using a service call from within my app's root component (AppComponent). The resulting data needs to be displayed by one or more other (child) components that are controlled by the RouterModule. For example:
export class AppComponent implements OnInit {
constructor(private _myService: MyService){ }
ngOnInit() {
this._myService.getSomeData().subscribe(theData => {
// theData needs to be displayed in ChildComponenet1 and / or ChildComponent2
}, err => {
console.log(err);
});
}
}
And my AppModule sets up routes using RouterModule:
@NgModule({
declarations: [
AppComponent
],
imports: [
RouterModule.forRoot([
{ path: 'child-component-1', component: ChildComponent1 },
{ path: 'child-component-2', component: ChildComponent2 },
]),
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
I want to avoid making an http request every time a user navigates to a /child-component, which is why I need to load the data from the AppComponent. (Or maybe I am approaching this the wrong way?)
This must be a fairly common pattern, any advice on the best way to approach this would be helpful. Thank you!
If this is just a simple app then what was suggested above to use a Service would be the best approach.
Another approach would be to have a look at state management using ngrx.
Here's an example of how you would do it (untested):
// data.ts
import { ActionReducer, Action } from '@ngrx/store';
export const STOREDATA = 'STORE_DATA';
export function dataReducer(state: data = null, action: Action) {
switch (action.type) {
case STOREDATA:
return action.payload;
default:
return state;
}
}
In your app's main module, import those reducers and use the StoreModule.provideStore(reducers) function to provide them to Angular's injector:
import { NgModule } from '@angular/core'
import { StoreModule } from '@ngrx/store';
import { dataReducer } from './data';
@NgModule({
imports: [
BrowserModule,
StoreModule.provideStore({ data: dataReducer })
]
})
export class AppModule {}
Then in your AppComponent
import { Store } from '@ngrx/store';
import { STOREDATA } from './data';
interface AppState {
data: any;
}
export class AppComponent implements OnInit {
constructor(private _myService: MyService, private store: Store<AppState>){ }
ngOnInit() {
this._myService.getSomeData().subscribe(theData => {
this.store.dispatch({ type: STOREDATA, payload: theData });
}, err => {
console.log(err);
});
}
}
In you child component:
import { Store } from '@ngrx/store';
import { STOREDATA } from './data';
interface AppState {
data: any;
}
export class AppComponent implements OnInit {
public data:any;
constructor(private store: Store<AppState>){
this.data = this.store.select('data');
}
}