Reputation: 1759
How would I remove a query parameter from the URL? For example from www.expample.com/home?id=123&pos=sd&sd=iii
to www.expample.com/home?id=123&sd=iii
EDIT: This is my version:
this.activatedRoute.queryParams.subscribe(c => {
const params = Object.assign({}, c);
delete params.dapp;
this.router.navigate([], { relativeTo: this.activatedRoute, queryParams: params });
}).unsubscribe();
Upvotes: 109
Views: 177266
Reputation: 605
I had to change a QP and remove one at the same time (change speciality
and remove set-title
). I tried having two different functions, but this process is async
and the router takes into consideration only its last call. So, here is my approach:
onSpecialityClick(speciality: Speciality): void {
// Get the current query parameters
const currentParams = { ...this.route.snapshot.queryParams };
// Update the speciality query parameter
currentParams['speciality'] = String(speciality.id);
// Remove the `set-title` query parameter
delete currentParams['set-title'];
// Apply the updated query parameters in a single navigation action
this.router
.navigate([], {
relativeTo: this.route,
queryParams: currentParams,
})
.then(() => {
// Do whatever you want in here (e.g. fetching some data)
});
}
Upvotes: 0
Reputation: 11
This solution works very well:
async removeQueryParams(keys: string[]) {
if (keys?.length) {
const queryParams01 = { ...this._ActivatedRoute.snapshot.queryParams };
keys.forEach((key) => {
delete queryParams01[key];
});
await this._Router.navigate([], {
relativeTo: this._ActivatedRoute,
queryParams: queryParams01,
queryParamsHandling: "",
replaceUrl: true,
});
}
}
Upvotes: 1
Reputation: 39
None of the above solution was fine for me. Until i tried this approach.
import { Component } from '@angular/core';
import { Location } from '@angular/common';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent {
constructor(private location: Location) { }
changeUrl() {
const newUrl = '/prepare/this/url/yourself/and/exclude/parameter';
this.location.replaceState(newUrl);
}
}
This replaces the parameter's version of URL with newUrl and good thing is that the components don't get re-rendered.
For more info about replaceState here it is.
Upvotes: -1
Reputation: 6039
I was looking to do exactly this, but without using the router. Here is what I came up with:
import { Location } from '@angular/common';
import { HttpParams } from '@angular/common/http';
declare location: Location; // get this from dependency injection
const [path, query] = location.path().split('?');
const params = new HttpParams({ fromString: query });
const theValueIWant = params.get('theParamIWant');
location.replaceState(path, params.delete('theParamIWant').toString());
Upvotes: 6
Reputation: 59
This worked for me:
Step 1: Declare a global url search param.
incomingUrlParams: URLSearchParams;
Step 2: Save the query in the urlsearchparam global variable
this.incomingUrlParams = new URLSearchParams(window.location.search);
Step 3: Call this anywhere when the params has been saved:
clearQueryParamenters() {
let queryParamsJsonString: string = "";
this.incomingUrlParams.forEach(function(value, key) {
queryParamsJsonString += '"' + key + '":' + null + ',';
});
queryParamsJsonString = "{" + queryParamsJsonString.trim().replace(/(^,)|(,$)/g, "") + "}";
this.router.navigate([], {
queryParams: JSON.parse(queryParamsJsonString),
queryParamsHandling: 'merge'
})
}
Upvotes: 0
Reputation: 49
Removing Query Params:
import { Router, ActivatedRoute, Params } from '@angular/router';
constructor(private router: Router, private activatedRoute: ActivatedRoute){
}
setQueryParams(){
const qParams: Params = {};
this.router.navigate([], {
relativeTo: this.activatedRoute,
queryParams: qParams,
queryParamsHandling: ''
});
}
Upvotes: 3
Reputation: 817
I've written a few Router Prototype overrides that makes things easier to handle query params:
The idea is to call a method on the router to easily manage routing via parameters, instead of having to export functions/redeclare the functionality every time.
Create an index.d.ts
file that contains the prototype override definitions:
// Ensure this is treated as a module.
export { };
declare module '@angular/router' {
interface Router {
updateQueryParams(activatedRoute: ActivatedRoute, params: Params): Promise<boolean>;
setQueryParams(activatedRoute: ActivatedRoute, params: Params): Promise<boolean>;
removeQueryParams(activatedRoute: ActivatedRoute, ...keys: string[]): Promise<boolean>;
}
}
Important:
Make sure you import this file before using this prototype override, I just added my prototype import(s) to the
app.module.ts
:
import './shared/prototype-overrides/router.prototypes';
This will only set the query parameters specified, and not merge the parameters.
You are on the following route:
http://localhost:4200/#/some-route?param1=Test¶m2=test2
and you want to SET the query parameters to param3=HelloWorld
, removing the others.
this.router.setQueryParams(this.activatedRoute, { param3: 'HelloWorld' });
// Will route to http://localhost:4200/#/some-route?param3=HelloWorld
Router.prototype.setQueryParams = function (activatedRoute: ActivatedRoute, params: Params): Promise<boolean> {
const context: Router = this;
if (isNullOrUndefined(activatedRoute)) {
throw new Error('Cannot update the query parameters - Activated Route not provided to use relative route');
}
return new Promise<boolean>((resolve) => {
setTimeout(() => {
resolve(context.navigate([], {
relativeTo: activatedRoute,
queryParams: params
}));
});
});
};
This is used to just easily update the queryParams, which will merge the query parameters in the route, so you don't have duplicate query parameters.
You are on the following route:
http://localhost:4200/#/some-route?param1=Test¶m2=test2
and you want to UPDATE only the one query parameter, param1
to param1=HelloWorld
, and leave the others as they are.
this.router.updateQueryParams(this.activatedRoute, { param1: 'HelloWorld' });
// Will route to http://localhost:4200/#/some-route?param1=HelloWorld¶m2=test2
Router.prototype.updateQueryParams = function (activatedRoute: ActivatedRoute, params: Params): Promise<boolean> {
const context: Router = this;
if (isNullOrUndefined(activatedRoute)) {
throw new Error('Cannot update the query parameters - Activated Route not provided to use relative route');
}
// setTimeout required because there is an unintended behaviour when rapidly firing router updates in the same repaint cycle:
//
// NavigationCancel - Navigation ID 2 is not equal to the current navigation id 3
// https://stackoverflow.com/a/42802182/1335789
return new Promise<boolean>((resolve) => {
setTimeout(() => {
resolve(context.navigate([], {
relativeTo: activatedRoute,
queryParams: params,
queryParamsHandling: 'merge'
}));
});
});
};
You are on the following route:
http://localhost:4200/#/some-route?param1=Test¶m2=test2¶m3=test3
and you want to REMOVE only the one (or more, separated keys by string) query parameter, param1
, and leave the others as they are.
this.router.removeQueryParams(this.activatedRoute, 'param1');
// Will route to http://localhost:4200/#/some-route?param2=test2¶m3=test3
//Removing multiple parameters:
this.router.removeQueryParams(this.activatedRoute, 'param1', 'param3');
// Will route to http://localhost:4200/#/some-route?param2=test2
Router.prototype.removeQueryParams = function (activatedRoute: ActivatedRoute, ...keys: string[]): Promise<boolean> {
const context: Router = this;
const currentParams: any = {};
Object.keys(activatedRoute.snapshot.queryParams).forEach(key => {
currentParams[key] = activatedRoute.snapshot.queryParams[key];
});
keys?.forEach(key => {
delete currentParams[key];
});
return new Promise<boolean>((resolve) => {
setTimeout(() =>
resolve(context.setQueryParams(activatedRoute, currentParams))
);
});
};
Upvotes: 2
Reputation: 5794
You can remove a query parameter by using the merge
option of queryParamsHandling
and passing in null
for any params you wish to remove.
// Remove query params
this.router.navigate([], {
queryParams: {
'yourParamName': null,
'youCanRemoveMultiple': null,
},
queryParamsHandling: 'merge'
})
This option is simpler and requires less work to ensure you are not removing other params. You also do not need to worry about cleaning up an observable subscription when your component is destroyed.
Upvotes: 294
Reputation: 1535
You can use native javascript operation to remove queryParams from url and navigate to View using navigateByUrl
method
https://angular.io/api/router/Router#navigateByUrl
this.route.queryParams
.subscribe((params: Params) => {
if (params && Object.keys(params).length > 0) {
const urlWithoutQueryParams = this.router.url.substring(0, this.router.url.indexOf('?'));
this.router.navigateByUrl(urlWithoutQueryParams)
.then(() => {
// any other functionality when navigation succeeds
params = null;
});
}
});
Upvotes: 1
Reputation: 8306
UPDATE: @epelc's answer below is the up-to-date and correct way to do this: https://stackoverflow.com/a/52193044/5932590.
Unfortunately, there is no clear-cut way to do this currently: https://github.com/angular/angular/issues/18011. However, as jasonaden commented on the linked thread,
This could be done manually by merging the old and new query params, removing the key you don't want.
Here is one way to do that:
Let's say you have your queryParams stored in some properties.
class MyComponent() {
id: string;
pos: string;
sd: string;
constructor(private route: ActivatedRoute, private router: Router) {}
ngOnInit() {
this.route.url.subscribe(next => {
const paramMap = next.queryParamMap;
this.id = paramMap.get('id');
this.pos = paramMap.get('pos');
this.sd = paramMap.get('sd');
});
}
}
A method to clear the pos
parameter would look like this:
clearPosParam() {
this.router.navigate(
['.'],
{ relativeTo: this.route, queryParams: { id: this.id, sd: this.sd } }
);
}
This will effectively navigate to the current route and clear your pos
query parameter, keeping your other query parameters the same.
Upvotes: 32
Reputation: 541
This is the best sulotion that i found, you can change url parameters
in constructor use
private _ActivatedRoute: ActivatedRoute
then use this in init or in constructor body
var snapshot = this._ActivatedRoute.snapshot;
const params = { ...snapshot.queryParams };
delete params.pos
this.router.navigate([], { queryParams: params });
Upvotes: 3