People working on laptops

Extend Angular Router to Support Encoding Characters

by Nikita Verkhoshintcev

Today I would like to talk about a particular case when building an Angular application.

I, personally, face this issue while building an online banking integration to Salesforce.

TUPAS is a digital authentication method created by the Federation of Finnish Financial Services.

The actual problem was with special characters such as “äö,” so-called ääkköset in Finnish.

Because TUPAS supports only ISO 8859-1 (Latin-1) encoding the browser converts them using an escaping character “%.”

Angular Router’s URL parser cannot parse it so that it would break the whole application.

In this article, I will show how you can extend the standard framework functionality and eventually resolve the issue.

The problem

First of all, let’s figure out where the error appears. We already know that the problem is with the router module.

The router is using the UrlSerializer to parse and serialize the URL. It has two corresponding methods. The first one accepts a string value and returns a UrlTree, and the other does the opposite.

Parse is the method which gives an error because of a particular character.

In general, people suggest pre-modifying the URL on the back-end side before sending to the Angular Router, e.g., using the proxy to return the URL with UTF-8 encoding.

I used that approach for one of the client projects with Salesforce to prevent VisualForce pages from breaking.

Though the solution works fine, it requires additional effort.

What I would like to do is to show how you can fix it on the front-end side.

The solution

The solution itself is a pretty trivial one. We already know that the escape char is the reason behind the issue so what we have to do is to unescape a string before passing it to the parse method of the UrlSerializer class.

The most exciting part is how to do it because it’s a default Angular class.

In fact, you can extend or modify any part of Angular by writing custom classes and provide them to the module.

As an example, you might want to do this to build a custom router state serializer when using NGRX store (Redux implementation for Angular using Reactive-Functional paradigm).

That is how you can do this.

Let’s create a file with the following code.

// custom-url-serializer.ts
import { UrlSerializer, UrlTree, DefaultUrlSerializer } from '@angular/router';
 
export class CustomUrlSerializer implements UrlSerializer {
  parse(url: any): UrlTree {
    const dus = new DefaultUrlSerializer();
    return dus.parse(unescape(url));
  }
 
  serialize(tree: UrlTree): any {
    const dus = new DefaultUrlSerializer();
    return dus.serialize(tree);
  }
}

It’s a custom class which implements the default UrlSerializer, and the only difference is that it uses the unescape function inside the parse method.

Then we need to navigate to our module file, import the class we just created and use it for the UrlSerializer in the providers.

// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { UrlSerializer } from '@angular/router';
import { AppComponent } from 'app/app.component';
import { CustomUrlSerializer } from './custom-url-serializer';
 
@NgModule({
  imports: [
    BrowserModule
  ],
  declarations: [ AppComponent ],
  providers: [
    { provide: UrlSerializer, useClass: CustomUrlSerializer }
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

That is it, the straightforward solution to our problem.

One of the cool things I like about the Angular is that you can rewrite any default functionality using the given approach.

Of course, in the majority of cases, you won’t have to do it, but still, it might be good to have in your arsenal.

Nikita Verkhoshintcev photo

Nikita Verkhoshintcev

Salesforce Consultant

Senior Salesforce and full-stack web developer. I design and build modern Salesforce, React, and Angular applications for enterprises. Usually, companies hire me when complex implementation, custom development and UI is required.

Let's work together!

Contact us today and take your digital end-user experience to the next level.

Contact us