In Angular2, is there a way to update a matrix parameter, but navigate to the same ponent? Basically would like to transition easily from a url that looks like:
/search;term=paris;pageSize=24;currentPage=1;someFilter=value;
to the same thing, but with currentPage updated upon pagination:
/search;term=paris;pageSize=24;currentPage=2;someFilter=value;
using router.navigate
hasn't appeared to be the best option, since I'd have to write plenty of my own logic to re-construct the url for navigate
's use (re-constructing something that already exists).
For kicks and giggles, I did try
this._router.navigate([this._router.url, {currentPage: this.pagination.currentPage}]);
but (as you might expect), the router is dumb to the fact that there are matrix parameters on the current url, so the result is not pretty.
EDIT: Should also mention that there may be any number of additional key/value pairs of matrix parameters, so hard-coding any route is out of the question
EDIT: I've since tried to use preserveQueryParams: true
like:
this._router.navigate(["..", {currentPage: this.pagination.currentPage}], {preserveQueryParams: true});
in order to get to an easily usable/transferable solution, but that did not keep the matrix params on the route.
UPDATE: I've since implemented my own logic to get the required behavior, so here's a code snippet for the solution:
let currentParamsArr: Params = this.route.snapshot.params;
let currentParamsObj: any = { };
for (let param in currentParamsArr) {
currentParamsObj[param] = currentParamsArr[param];
}
currentParamsObj.currentPage = +pageNum; //typecasting shortcut
this._router.navigate([currentParamsObj], { relativeTo: this.route });
This code loops through the parameters (as they stand in the snapshot), and creates an object out of them, then adds/edits the parameter that I desire to update, then navigates to the "new" route
But, this is not pretty, as I'll essentially have this same logic in many places of the program or have to make a modification to Router or provide some other generic method.
In Angular2, is there a way to update a matrix parameter, but navigate to the same ponent? Basically would like to transition easily from a url that looks like:
/search;term=paris;pageSize=24;currentPage=1;someFilter=value;
to the same thing, but with currentPage updated upon pagination:
/search;term=paris;pageSize=24;currentPage=2;someFilter=value;
using router.navigate
hasn't appeared to be the best option, since I'd have to write plenty of my own logic to re-construct the url for navigate
's use (re-constructing something that already exists).
For kicks and giggles, I did try
this._router.navigate([this._router.url, {currentPage: this.pagination.currentPage}]);
but (as you might expect), the router is dumb to the fact that there are matrix parameters on the current url, so the result is not pretty.
EDIT: Should also mention that there may be any number of additional key/value pairs of matrix parameters, so hard-coding any route is out of the question
EDIT: I've since tried to use preserveQueryParams: true
like:
this._router.navigate(["..", {currentPage: this.pagination.currentPage}], {preserveQueryParams: true});
in order to get to an easily usable/transferable solution, but that did not keep the matrix params on the route.
UPDATE: I've since implemented my own logic to get the required behavior, so here's a code snippet for the solution:
let currentParamsArr: Params = this.route.snapshot.params;
let currentParamsObj: any = { };
for (let param in currentParamsArr) {
currentParamsObj[param] = currentParamsArr[param];
}
currentParamsObj.currentPage = +pageNum; //typecasting shortcut
this._router.navigate([currentParamsObj], { relativeTo: this.route });
This code loops through the parameters (as they stand in the snapshot), and creates an object out of them, then adds/edits the parameter that I desire to update, then navigates to the "new" route
But, this is not pretty, as I'll essentially have this same logic in many places of the program or have to make a modification to Router or provide some other generic method.
Share Improve this question edited Dec 20, 2016 at 4:50 CozyAzure 8,4787 gold badges38 silver badges55 bronze badges asked Dec 18, 2016 at 6:06 CorbfonCorbfon 3,6441 gold badge14 silver badges24 bronze badges 7-
Perhaps
this._router.navigate([this._router.url, {currentPage: this.pagination.currentPage}], {preserveQueryParams: true});
– Günter Zöchbauer Commented Dec 18, 2016 at 12:09 - sounds like the right path! Just gave it a shot, and no dice. I think the issue has something to do with this._router.url being a string (it still encoded the semicolons). Is there a more plex object that the navigate method could be used with, which would still contain the query params explicitly? – Corbfon Commented Dec 18, 2016 at 15:45
-
This gets me almost where I want:
this._router.navigate(["..", {currentPage: this.pagination.currentPage}]);
, except that it tosses the other query parameters. Also tried adding{preserveQueryParams: true}
here and it didn't alter behavior – Corbfon Commented Dec 18, 2016 at 15:50 -
1
I guess you need to build a new urlTree using
this._router.createUrlTree()
where you pass the parts that build the route by getting them fromActivatedRoute
orthis._router..routerState
and traverse the route tree to get all parts. I don't know of an easier way. – Günter Zöchbauer Commented Dec 18, 2016 at 15:52 - 1 @GünterZöchbauer you were right about making a urlTree. I think it's probably the cleanest approach. I've posted the implementation in an answer – Corbfon Commented Jan 25, 2017 at 17:43
3 Answers
Reset to default 5The approach that ended up working well for me is this:
let route: ActivatedRoute;
const newUrl = router.createUrlTree([
merge({'a': 123}, route.snapshot.params)
], {relativeTo: route});
By using merge, you can add, update and subtract url parameters and then use router.navigateByUrl(newUrl)
in order to execute.
add: merge({newParam: 111}, route.snapshot.params)
update: merge({param: 111}, route.snapshot.params)
subtract: merge({param: null}, route.snapshot.params)
Hope others find this as useful as I have.
Another example using Object.assign instead of merge:
let route = this.route; // The imported ActivatedRoute
let currentParamsObj: Params = Object.assign({}, route.snapshot.params);
let newParam = {};
newParam[key] = value;
let newUrl = this._router.createUrlTree([
Object.assign(currentParamsObj, newParam)
], {relativeTo: this.route });
this._router.navigateByUrl(newUrl);
Have you tried using something like
this._router.navigateByUrl('/search;term='+this.term+';pageSize='+this.pageSize+';currentPage='+this.currentPage+';someFilter='+this.someFilter;
In my case, I had a parent and child router, with params on the parent I needed to modify:
/my-parent;x=1;y=2/my-child
Working off of @Corbfon's solution, I was able to modify the parent route like this:
// modify the context params in the PARENT route
const newParam = {'z': '3'};
const parentParams: Params = Object.assign({ ...this.activatedRoute.parent.snapshot.params }, newParam);
// note: this approach doesn't preserve params on the child route (but there aren't any in my case)
const currentChildPath = this.activatedRoute.routeConfig.path;
// notice it's relativeTo the parent route
const newUrl = this.router.createUrlTree([parentParams, currentChildPath],
{relativeTo: this.activatedRoute.parent});
this.router.navigateByUrl(newUrl);
Hope this helps someone else.
P.S. Don't forget to use .snapshot.params
instead of .params
on the ActivatedRoute
.