Angular 4 ngOnInit component not called for every route request

I recently started diving into Angular 4, starting with Angular 1.5. I work with custom routes and pull API data from a service into a user component.

The component seems to remain static, unlike the controllers in 1. *, where they were updated for each request.

Is there anyway the ngOnInit function called with every new route request?

My custom component class:

// url structure: /user/:id export class UserComponent implements OnInit { constructor(private route: ActivatedRoute) {} ngOnInit() { // doesn't log new id on route change let id = this.route.snapshot.params['id']; console.log(id); this.route.params .switchMap(params => this.userService.getUser(params['id'])) .subscribe(user => { // logs new id on route change let id = this.route.snapshot.params['id']; console.log(id); this.user = user }); } } 

UPDATE

Found a solution that I think works best for my scenario. Based on a few answers and comments on my question and further investigation, signing up for a route seems to be a way out. Here is my updated component:

 export class UserComponent { user; id; constructor( private userService: UserService, private route: ActivatedRoute ) {} ngOnInit() { this.route.params .subscribe(params => this.handleRouteChange(params)); } handleRouteChange(params) { this.id = params['id']; switch (this.id) { case '1': console.log('User 1'); break; case '2': console.log('User 2'); break; case '3': console.log('User 3'); break; } this.userService.getUser(this.id). subscribe(user => this.user = user); } } 
+5
source share
3 answers

Angular prefers - by default - to reuse the same component instead of introducing a new one if the route is the same, but the parameters change.

Good news ! this is custom behavior, you can force the initiation of a new instance of the component by implementing your own RouteReuseStrategy :

 export class MyRouteReuseStrategy extends DefaultRouteReuseStrategy { shouldReuseRoute(next: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean { let name = next.component && (next.component as any).name; return super.shouldReuseRoute(next, current) && name !== 'UserComponent'; } } 

in your module:

 @NgModule({ ... providers:[{ provide: RouteReuseStrategy, useClass: MyRouteReuseStrategy}] ... }) export class AppModule {} 

(this code is more or less taken from in this article , especially checking the name property, which may not be very accurate ...)

Please note that this may be some performance penalty when restoring the same component. Therefore, you might be better off using observable properties instead of snapshots.

+2
source

Is the URL similar to "...? Id = 1" or "../:id" and you want the component to register the identifier every time the GET parameter changes? The problem here is about. The best solution I have found is here . I have not tested it myself, but that should work.

The second link shows how to sign up for a route change within a component, which, in my opinion, is what you are trying to do. This will allow you to handle the change in the GET parameter inside ngOnInit . I'm not sure if the route subscription will start when you start navigating to the URL, so you might want to have a function that handles the route event call a doCheck() , and change ngOnInit to ngAfterContentInit

ngOnInit only works in change detection , and changing GET does not seem to cause it, which is surprising to me.

Tl; dr - Subscribe to the route change event in the constructor and create a function that processes the emitted event. The function must contain the logic available in ngOnInit ().

0
source

Hi, you need to use switchMap as follows:

 this.sub = this.route.paramMap .switchMap((params: ParamMap) => this.firebaseService.getProductsByCategory(params.get('category'))).subscribe(products => { this.products = products; this.count = products.length; }); 

This work is for me.

0
source

All Articles