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.
Angular2 by default uses encodeURIComponent() to encode queryParams in URL, you can avoid it by writing custom URL serializer and override default functionality.
In my case, I wanted to avoid Angular2 to avoid replacing comma(,) by (%2). I was passing Query as lang=en-us,en-uk where it was getting converted to lang=en-us%2en-uk.
Here how I worked it out:
CustomUrlSerializer.ts
import {UrlSerializer, UrlTree, DefaultUrlSerializer} from '@angular/router';
export class CustomUrlSerializer implements UrlSerializer {
parse(url: any): UrlTree {
let dus = new DefaultUrlSerializer();
return dus.parse(url);
}
serialize(tree: UrlTree): any {
let dus = new DefaultUrlSerializer(),
path = dus.serialize(tree);
// use your regex to replace as per your requirement.
return path.replace(/%2/g,',');
}
}
Add below line to your main appModule.ts
import {UrlSerializer} from '@angular/router';
import {CustomUrlSerializer} from './CustomUrlSerializer';
@NgModule({
providers: [{ provide: UrlSerializer, useClass: CustomUrlSerializer }]
})
This won't break your default functionality and take cares of URL as per your need.
Try:
this.router.navigateByUrl(url) // replace 'url' with whatever you'd like.
Note, this excepts a string, so unlike 'this.router.navigate', you don't use the [] brackets.
Update: with the new httpParamSerializer in Angular 1.4 you can do it by writing your own paramSerializer and setting $httpProvider.defaults.paramSerializer.
Below only applies to AngularJS 1.3 (and older).
It is not possible without changing the source of AngularJS.
This is done by $http:
https://github.com/angular/angular.js/tree/v1.3.0-rc.5/src/ng/http.js#L1057
function buildUrl(url, params) {
if (!params) return url;
var parts = [];
forEachSorted(params, function(value, key) {
if (value === null || isUndefined(value)) return;
if (!isArray(value)) value = [value];
forEach(value, function(v) {
if (isObject(v)) {
v = toJson(v);
}
parts.push(encodeUriQuery(key) + '=' +
encodeUriQuery(v));
});
});
if(parts.length > 0) {
url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
}
return url;
}
encodeUriQuery uses the standard encodeUriComponent (MDN) which replaces the '+' with '%2B'
Too bad you cannot overwrite encodeUriQuery because it is a local variable inside the angular function.
So the only option I see is to overwrite window.encodeURIComponent. I've done it in an $http interceptor to minimize the impact. Note that the original function is only put back when the response comes back, so this change is global (!!) while your request is ongoing. So be sure to test if this doesn't break something else in your application.
app.config(function($httpProvider) {
$httpProvider.interceptors.push(function($q) {
var realEncodeURIComponent = window.encodeURIComponent;
return {
'request': function(config) {
window.encodeURIComponent = function(input) {
return realEncodeURIComponent(input).split("%2B").join("+");
};
return config || $q.when(config);
},
'response': function(config) {
window.encodeURIComponent = realEncodeURIComponent;
return config || $q.when(config);
}
};
});
});
AngularJS only runs the encodeUriQuery method if you pass your params as an extra object. If you manually create your own param string and concatenate it onto your URL then Angular won't modify it.
It's pretty simple to convert the param object yourself, here's an example: How to serialize an Object into a list of parameters?
I was able to fix by passing a type of any to my state's url queryParam since it is not encoded by UrlMatcherFactory by updating the /state?:param to /state?{param:any} since this is expected behavior for ~ to ~~. More details can be found here: https://github.com/angular-ui/ui-router/issues/3790
With the new httpParamSerializer in AngularJS you can do it by writing your own paramSerializer and setting $httpProvider.defaults.paramSerializer.
Angular2 by default uses encodeURIComponent() to encode queryParams in URL, you can avoid it by writing custom URL serializer and override default functionality.
In my case, I wanted to avoid Angular2 to avoid replacing comma(,) by (%2). I was passing Query as lang=en-us,en-uk where it was getting converted to lang=en-us%2en-uk.
Here how I worked it out:
CustomUrlSerializer.ts
import {UrlSerializer, UrlTree, DefaultUrlSerializer} from '@angular/router';
export class CustomUrlSerializer implements UrlSerializer {
parse(url: any): UrlTree {
let dus = new DefaultUrlSerializer();
return dus.parse(url);
}
serialize(tree: UrlTree): any {
let dus = new DefaultUrlSerializer(),
path = dus.serialize(tree);
// use your regex to replace as per your requirement.
return path.replace(/%2/g,',');
}
}
Add below line to your main appModule.ts
import {UrlSerializer} from '@angular/router';
import {CustomUrlSerializer} from './CustomUrlSerializer';
@NgModule({
providers: [{ provide: UrlSerializer, useClass: CustomUrlSerializer }]
})
This won't break your default functionality and take cares of URL as per your need.
You can't prevent slashes from being encoded. I'd use matrix parameters which look cleaner.
http://page.com/home/example;a=foo;b=bar;c=baz/something
You can use Router's navigate method to use them
this.router.navigate(['/home', '/example', { a: 'foo', b: 'bar', c: 'baz' }, '/something']);
To get current params, use ActivatedRoute's params property to which you can subscribe.
I've used this scope function to solve my issue:
$scope.beautyUri = function (uuid, title) {
return decodeURIComponent($state.href("show.hastitle", {uuid: uuid, title: title}));
};
and use this function in html like this:
<a href="{{beautyUri(item.uuid, item.title)}}">{{title}}</a>
i hade this problem to but after a lot of unsuccessful searches , find the solution it's very simple actually
you can use javaScript decodeURIComponent() function on $scope.item.title for me it's worked like charm .