Search code examples
angularrxjsangular-routing

get only final value from angular queryParams


My goal is to find out if the query param project is set at loading of the application. Whilst I also have to load a list of projects. When I got both informations I can proceed with my logic.

Here is what I got so far

combineLatest([
  this.route.queryParams.pipe(pluck('project')),
  this.projects$.pipe(first(),filter(p => p && p.length > 0))
]).subscribe(([projectParam, projects]) => {
  console.log(projectParam, projects);
});

The this.routeis of type ActivatedRoute: https://angular.io/api/router/ActivatedRoute

The projects$ observable works ideally. But the queryParams observable is being called twice. Once with the value undefined and then later on with the real value. But I just want the last value. Since the url is optional both options are valid.

Any idea how I can make queryParams just fire on the final value.


Solution

  • Thanks to the discussion here: https://github.com/angular/angular/issues/12157 I came up with the following solution:

    private get finalQueryParams$(): Observable<Params> {
      return merge(
        // get urls with query params like /test?project=test
        this.route.queryParams.pipe(
          filter(params => Object.keys(params).length > 0)
        ),
        // get urls without query params like /test
        this.route.queryParams.pipe(
          filter(() => !(window.location.href || '').includes('?')),
          map(() => ({}))
        )
      );
    }
    

    It fires just once and I get the real value of the queryParams.

    In the code above I then just had to change it to

    combineLatest([
      this.finalQueryParams$.pipe(pluck('project')),
      this.projects$.pipe(first(),filter(p => p && p.length > 0))
    ]).subscribe(([projectParam, projects]) => {
      console.log(projectParam, projects);
    });