I am using an Angular 2 Router to update the query params in a URL for a search application. I am attempting to replace spaces in a query with + signs. However, + signs are getting encoded. For example:
this.router.navigatebyUrl('?q=one+two');
populates the URL with "?q=one%2Btwo".
In looking at the source code for Angular 2, it looks like the router converts the URL to a UrlTree which uses encodeURIComponent() to encode the url. Because of this, it is impossible to prevent the default encoding.
My current process is that I change the route by doing navigateByUrl as seen above, and then listen for changes with:
this.routeSubscription = this.route.queryParams.subscribe((params: any) => {
this.term = (params.q ? params.q : '');
});
Is there an alternate way to deal with query parameters that would allow me to use my own strategy for url encoding?
populates the URL with "?q=one%2Btwo". In looking at the source code for Angular 2, it looks like the router converts the URL to a UrlTree which uses encodeURIComponent () to encode the url. Because of this, it is impossible to prevent the default encoding.
However, + signs are getting encoded. For example: populates the URL with "?q=one%2Btwo". In looking at the source code for Angular 2, it looks like the router converts the URL to a UrlTree which uses encodeURIComponent () to encode the url.
Using the Angular CLI, create a new application, angular-custom-route-match . In addition to the default Angular application framework, you will also create a profile component. Create a new Angular project, angular-custom-route-match. When prompted with Would you like to add Angular routing?, select Y.
Pattern matching with the Angular Router provides you with a lot of flexibility when you have dynamic URLs in your application. To learn more about the Angular Router, see the following topics: This content is based on Custom Route Matching with the Angular Router, by Brandon Roberts.
I was able to find a solution to my problem. You can make own custom url serializer by implementing the UrlSerializer class.
Custom Url Serializer
Create a custom url serializer like this:
class CustomUrlSerializer implements UrlSerializer {
parse(url: string): UrlTree {
// Custom code here
}
serialize(tree: UrlTree): string {
// Custom code here
}
}
Then, you just need to provide the CustomUrlSerializer in place of the UrlSerializer, which you can place in the AppModule providers array after importing both serializers.
providers: [
{ provide: UrlSerializer, useClass: CustomUrlSerializer },
...
]
Now, when you call router.navigate or router.navigateByUrl, it will use your custom serializer for parsing and serializing.
Using + signs as spaces
To parse + signs as spaces:
parse(url: string): UrlTree {
// Change plus signs to encoded spaces
url = url.replace(/\+/g, '%20');
// Use the default serializer that you can import to just do the
// default parsing now that you have fixed the url.
return this.defaultUrlSerializer.parse(url)
}
And for serializing:
serialize(tree: UrlTree): string {
// Use the default serializer to create a url and replace any spaces with + signs
return this.defaultSerializer.serialize(tree).replace(/%20/g, '+');
}
DefaultUrlSerializer
I ran into an issue specifying the custom provider. There was apparently a circular dependency when compiling with the --prod flag causing an error with the text: useClass cannot by null. This is how I worked around that error:
In AppModule, define the following:
const customUrlSerializer = new CustomUrlSerializer();
const CustomUrlSerializerProvider = {
provide: UrlSerializer,
useValue: customUrlSerializer
};
Then in the providers array, add the provider you specified above.
...
providers: [CustomUrlSerializerProvider]
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With