I have angular application where i want to pass plus sign + in query string like:
http://localhost:3000/page?name=xyz+manwal
This is a quite common problem. You can pass it normally in application/x-www-form-urlencoded request. No other request will be able to correctly parse +. They will always parse it into %20 instead of %2B.
You would need to manually manipulate the query parameter, there are 2 ways:
For more info you should reffer to hthe following stack overflow questions Android: howto parse URL String with spaces to URI object? and URL encoding the space character: + or %20?
I have found solution and posting it for future reference. Angular js was converting +
sign into %2B
.
Following code prevented that:
.config([
'$provide', function($provide) {
$provide.decorator('$browser', function($delegate) {
let superUrl = $delegate.url;
$delegate.url = (url, replace) => {
if(url !== undefined) {
return superUrl(url.replace(/\%2B/g,"+"), replace);
} else {
return superUrl().replace(/\+/g,"%2B");
}
};
return $delegate;
});
}
])
In Angular v6.1.10, if you just need to fix the "+" sign encoding in one spot, this is what worked for me.
getPerson(data: Person) {
const httpParams = new HttpParams({
fromObject: {
id: data.id,
name: data.name,
other: "xyz+manwal"
}
});
// manually encode all "+" characters from the person details
let url = BASE_URL + "/select?" + httpParams.toString().replace(/\+/gi, '%2B');
return this.http.get(url);
}
I found if you try to replace the "+" signs when initializing the httpParams
object it doesn't work. You have to do the replacement after converting httpParams
to a string, as shown on this line:
let url = BASE_URL + "/select?" + httpParams.toString().replace(/\+/gi, '%2B');
This ia a common problem. The +
character is used by the URL to separate two words. In order to use the +
character in the parameter values, you need to encode your parameter values before adding them as part of the URL. Javascript / TypeScript provide a encodeURI()
function for that specific purpose.
URL encoding converts characters into a format that can be transmitted over the Internet. [w3Schools Reference]
Here is how you can fix this problem:
let encodedName = encodeURI('xyz+manwal');
let encodedURI = 'http://localhost:3000/page?name='+encodedName;
//.. OR using string interpolation
let encodedURI = `http://localhost:3000/page?name=${ encodedName }`;
In the same way, you can decode the parameters using decodeURI()
method.
let decodedValue = decodeURI(encodedValue);
In Angular 5.2.7+ the "+" is replaced with space " " in a query string.
Here is the corresponding commit : fix(router): fix URL serialization
If you want to change this behaviour and replace the "+" with "%2B" you can create a custom url serializer and provide it in the AppModule providers.
import { DefaultUrlSerializer, UrlSerializer, UrlTree } from '@angular/router';
export default class CustomUrlSerializer implements UrlSerializer {
private _defaultUrlSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();
parse(url: string): UrlTree {
// Encode "+" to "%2B"
url = url.replace(/\+/gi, '%2B');
// Use the default serializer.
return this._defaultUrlSerializer.parse(url);
}
serialize(tree: UrlTree): string {
return this._defaultUrlSerializer.serialize(tree).replace(/\+/gi, '%2B');
}
}
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule
],
declarations: [
AppComponent
],
providers: [
{ provide: UrlSerializer, useClass: CustomUrlSerializer }
],
entryComponents: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
http://localhost:3000/page?name=xyz+manwal
The URL will be converted to:
http://localhost:3000/page?name=xyz%2Bmanwal
Hope this will help.
I am using Angular 7, the + (this one "xyz+manwal") is replaced with a space (like this "xyz manwal") in the URI when it reaches to back-end code.
encodeURI() dindn't work for me, I used encodeURIComponent() it converted + to %2B
encodeURIComponent("xyz+manwal") => "xyz%2Bmanwal"
below is the example code
// filter = xyz+manwal
let filterString = encodeURIComponent(filter); // filterString = xyz%2Bmanwal
return this.http.get<ListResults>("http://website/query-results?" + filterString ).pipe(
retry(3),
catchError(........)
)