11

I have [routerLink] as below;

 <li *ngFor="let item of pageNumbers" class="page-item">
      <a
        class="page-link"
        [routerLink]="getPageUrl(item) | async"
        routerLinkActive="active"
        >{{ item }}</a
      >
    </li>

And getPageUrl method is like;

public getPageUrl(pageNumber: number): Observable<string> {
    const url: Observable<string> = this.route.url.pipe(
      map((segments: UrlSegment[]) => {
        let segmentsString = segments.join("/");
        let pageUrl = `/${segmentsString}?startIndex=${pageNumber}`;
        return pageUrl;
      })
    );
    return url;
  }

But on browser angular shows url like below;

http://localhost:3005/documents%3FstartIndex%3D1 

desired:

http://localhost:3005/documents?startIndex=1

Am I missing something here? I would simply bind pagination directly to [routerLink], but there will be more query string parameters (filters, sorting) will get in to URL, that’s why I am trying to generate URL dynamically.

Teoman shipahi
  • 47,454
  • 15
  • 134
  • 158

1 Answers1

12

Check the docs for RouterLink:

  • [routerLink] is used to pass what comes before the ?, called "params".
  • [queryParams] is used to pass what comes after the ?, called "query params".

So, to solve your issue, a possible solution is to return an object from getPageUrl instead of a string, the object will have both the params and query params:

public getPageUrl(pageNumber: number): Observable<string> {
    return this.route.url.pipe(
      map((segments: UrlSegment[]) => {
        return {params: segments, queryParams: {startIndex: pageNumber};
      })
    );
  }

and you use it like this:

<a *ngIf="getPageUrl(item) | async as url"
   class="page-link"
   [routerLink]="url.params"
   [queryParams]="url.queryParams">{{ item }}</a

Notice you don't need to join the query segments with /, because routerLink accepts an array too.

Daniel
  • 21,933
  • 14
  • 72
  • 101