Waiting for ngrx action before loading page with URL parameter

I am creating an ng2 application using ngrx. When the application starts, the web service is called to get the source data, after receiving this data, I create the INIT_DONE action.

My condition is as follows:

export interface State { documents: Document[]; selectedDocument: Document } 

When I go to the / mypage / 456 page, where 456 is the url parameter, I need to get some of the data received, so I get the URL parameter as follows:

 ngOnInit() { this.paramSubscription = this.route.params .select<string>('id') .map((id) => new SelectAction(id)) .subscribe(this.store); } 

SELECT_ACTION finds the item in the extracted data and sets selectedDocument . The problem is that SELECT_ACTION is created before INIT_DONE and at this point documents empty.

How to wait for INIT_DONE before loading my page?

+6
source share
3 answers

I would use the combineLatest operator, since it combines the last values ​​of several source streams. In addition, I would double check that the documents are installed (here I took it as an array) using a filter.

 ngOnInit() { this.subscription = Observable.combineLatest( this.store.select("documents") .filter(documents => documents.length > 0), this.paramSubscription = this.route.params .select<string>('id') ) .map((combinedData: [Object[], string]) => combinedData[1]) .subscribe(this.store); } 

Also assign a subscription to a variable so that you can unsubscribe when a component is destroyed. Otherwise, your subscription will be after the component is destroyed, and it is possible that your action is still emitted:

 ngOnDestroy() { this.subscription.unsubscribe(); } 
+6
source

You need a resolver. The examiner waits until data is available until the navigation action is complete.

 @Injectable() export class DocumentsResolver implements Resolve { constructor( private store: Store ) {} resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Hero> { // take id from snapshot const id = route.params['id']; // start with the document list return this.store.select('documents') // wait until there is data available .filter(documents => documents && documents.length > 0) // then produce the selected document .mergeMapTo(this.store.select('selectedDocument')); } } 

In the route configuration:

 export const DocumentsRoutes: RouterConfig = [ { path: 'documents/:id', component: DocumentsDetailComponent, resolve: { document: DocumentsResolver } } ]; 

Learn more about router resolution here.

+2
source

You can select documents from the store and subscribe to it and publish your action:

 ngOnInit() { this.store.select("documents").subscribe(documents => { this.paramSubscription = this.route.params .select<string>('id') .map((id) => new SelectAction(id)) .subscribe(this.store); }); } 
0
source

Source: https://habr.com/ru/post/1012740/


All Articles