36

For example I am on route /cars?type=coupe and I want to navigate to the same endpoint with additional query params (but keeping existing one). I am trying something like this

<a [routerLink]="['/cars']" [queryParams]="{model: 'renault'}" preserveQueryParams>Click</a>

The initial query params are preserved (type=cars) but added ones (model=renault) are ignored. Is this expected/correct behavior or is some kind of bug? Looks like preserveQueryParams has priority over queryParams? Is there any other smooth solution?

izupet
  • 1,529
  • 5
  • 20
  • 42

4 Answers4

48

In Angular 4+, preserveQueryParams has been deprecated in favor of queryParamsHandling. The options are either 'merge' or 'preserve'.

In-code example (used in NavigationExtras):

this.router.navigate(['somewhere'], { queryParamsHandling: "preserve" });

In-template example:

<a [routerLink]="['somewhere']" queryParamsHandling="merge">
DarkNeuron
  • 7,981
  • 2
  • 43
  • 48
  • 1
    Great answer! might want to use merge in your first example as it is the setting the OP wants – BradleyDotNET Dec 07 '17 at 18:21
  • Thank you for your answer, This should be the accepted answer, I have no idea why people are answering with a complex answers on a totally wrong directions!, as a RoR developer, never seen such as this mess anywhere among the community, and I'm saying this because I've had a real hard times finding a simple answer for a simple question :S, Thanks again for your answer :) – Amir El-Bashary Nov 29 '21 at 11:17
14

It just works this way unfortunately:

const q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams;

You could try to add custom directive like this:

@Directive({selector: 'a[routerLink][merge]'})
export class RouterLinkDirective implements OnInit
{

    @Input()
    queryParams: {[k: string]: any};

    @Input()
    preserveQueryParams: boolean;


    constructor(private link:RouterLinkWithHref, private route: ActivatedRoute )
    {
    }

    public ngOnInit():void
    {
        this.link.queryParams = Object.assign(Object.assign({}, this.route.snapshot.queryParams), this.link.queryParams);
        console.debug(this.link.queryParams);
    }
}


<a [routerLink]="['/cars']" merge [queryParams]="{model: 'renault'}">Click</a>

Update: See DarkNeuron answer below.

kemsky
  • 14,727
  • 3
  • 32
  • 51
1

There is an open issue and also already a pull request to make preserveQueryParams a router setting instead of a per navigation setting

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
0

This can be handled using relativeTo and queryParamsHandling properties.

Try like this:

constructor(private _route: ActivatedRoute, private _router: Router)


this._router.navigate(
    [],
    {
      relativeTo: this._route,
      queryParams: { model: 'renault' },
      queryParamsHandling: 'merge'
 });
Adrita Sharma
  • 21,581
  • 10
  • 69
  • 79