Search code examples
angularrxjsangular-ui-routerobservablengrx

Angular change component state from a service when route changes


I have a component called profile. It gets its data from user.service. Problem is that it does not change when the Route changes (on click, using 'routerLink'); I want to bring in new data from the service every time the route changes. I have tried Subscribing to the route param observable. But it returns an Observable of an Observable (I'm sure there are better ways of doing things).

Here's My Code

// imports ...

@Component({
  ...
})
export class ProfileComponent implements OnInit {
  $user: Observable<User>;
    
  constructor(private userService: UserService, private router: Router, private route: ActivatedRoute) {}
    
  ngOnInit() {
    // UserService.getSingleUser(string); returns Observable<User>;
    
    // Method 1 (Tried. failed)
    this.$user = this.userService.getSingleUser(this.router.url.sibstring(1));
    
    // Method 2 (Tried, failed)
    this.route.params.pipe(
      map(params => params.username),
      map(username => this.userService.getSingleUser(username))
    ).subscribe(response => {
      this.$user = response;
    });
    
    
    this.$user.subscribe({
      next: console.log,
      error: console.warn
    });
  }
}

Github Gist


Solution

  • You are most likely looking for a combination of your second method and switchMap (check this for a visualized explanation). It will allow you to exchange the running observable stream with a new inner one, in this case userService.getSingleUser.

    this.$user = this.route.params.pipe(
      map(params => params.username),
      switchMap(username => this.userService.getSingleUser(username))
    );
    

    The $user-observable should store the result from userService.getSingleUser. Not that you most likely want to double check if params.username exists. Depending on your route structures this may result in undefined. If you subscribe to the observable within your template, you will not have to worry about destroying the stream afterwards. If you plan to use .subscribe within your .ts file, remember to destroy the subscription properly, otherwise this will result in a leak.