I was upgrading my angular apps which run inside the Share Point office adds in. Currently angular app is using version 14, after I upgrade to angular 15 it works fine. But as soon as I upgrade to 16, I get below error.
TypeError: this._history.replaceState is not a function
This happens when calling
this.router.navigate(['/path_to_component']);
I found a fix on this SO post. Office.js nullifies browser history functions breaking history usage
<script type="text/javascript">
// Office js deletes window.history.pushState and window.history.replaceState. Cache them and restore them
window._historyCache = {
replaceState: window.history.replaceState,
pushState: window.history.pushState
};
</script>
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
<script type="text/javascript">
// Office js deletes window.history.pushState and window.history.replaceState. Restore them
window.history.replaceState = window._historyCache.replaceState;
window.history.pushState = window._historyCache.pushState;
</script>
I am not sure how this is breaking only after upgrade to Angular 16 though its relate to office.js
I am using the same version of office.js.
I have already use hash location strategy. Could any one help me to understand this.
Looking at Angular 14/15's source code, we can see that BrowserPlatformLocation
contains this method:
override replaceState(state: any, title: string, url: string): void {
if (supportsState()) {
this._history.replaceState(state, title, url);
} else {
this.location.hash = url;
}
}
Sources:
What you should notice is supportsState()
:
export function supportsState(): boolean {
return !!window.history.pushState;
}
In Angular 14/15 there's a fallback case if pushState
is not available, so you code works well and also this._history.replaceState()
works correctly.
From Angular 16, that check was removed:
override replaceState(state: any, title: string, url: string): void {
this._history.replaceState(state, title, url);
}
So, because office.js
removes pushState
and replaceState
and there's no fallback case, your code breaks (until you use the fix you already found).