# Implementing a custom angular location strategy

# Context

Angular provides two approaches for routing, called Location Strategies. They are the `HashLocationStrategy` and the `PathLocationStrategy`. One key difference is that the `HashLocationStrategy` puts a `#` in all component URLs, whereas the `PathLocationStrategy` does not. This means that it's a breaking change to move from one to the other, because any bookmarks your users have will stop working.

I was recently working with an application which had been set up using the `HashLocationStrategy`. I implemented an OAuth 2 login process and needed a callback URL which should be within the angular app. However, the OAuth 2 specification does not allow callback URLs to include a `#` character. 

I didn't want to break users' bookmarks by changing to use the `PathLocationStrategy`, but I also needed a URL which didn't contain a `#` for one specific component. What could I do which would meet both these requirements?

# The solution

I decided to implement my own `CustomHashLocationStrategy`, based on the built-in `HashLocationStrategy`. The callback route will not have a `#`, and the `CustomHashLocationStrategy` is responsible for detecting this route and adding the `#` to the front of it. This is the only custom behaviour, it is otherwise identical to `HashLocationStrategy`. This way, existing bookmarks will continue to work, because the app is still using the `HashLocationStrategy`.

# Code

This is the class I wrote. The only custom logic it contains is a single `if` statement.

```ts
import { APP_BASE_HREF, HashLocationStrategy, PlatformLocation } from '@angular/common';
import { Inject, Injectable, Optional } from '@angular/core';

@Injectable()
export class CustomHashLocationStrategy extends HashLocationStrategy {
    constructor(private platformLocation: PlatformLocation,
                @Optional() @Inject(APP_BASE_HREF) _baseHref?: string) {
        super(platformLocation, _baseHref);
    }

    path(includeHash: boolean = false): string {
        let path = this.platformLocation.hash;
        if (path == null) {
            path = '#';
        }

        // This if block is the only custom code in this class.
        // The rest is the same as the HashLocationStrategy.
        // https://github.com/angular/angular/blob/13.3.2/packages/common/src/location/hash_location_strategy.ts#L65
        if (location.pathname === '/path-to-callback') {
            path = `#${location.pathname}/${location.search}`;
        }

        return path.length > 0 ? path.substring(1) : path;
    }
}
```
