Back-button support HostNavigationService
cveld opened this issue · 1 comments
cveld commented
I am setting the address bar with the HostNavigationService
as follows:
import { IHostNavigationService } from "azure-devops-extension-api";
import * as SDK from "azure-devops-extension-sdk";
async function getNavigationService(): Promise<IHostNavigationService> {
const navService = await SDK.getService<IHostNavigationService>("ms.vss-features.host-navigation-service");
return navService;
}
this.navService = await getNavigationService();
this.navService!.setQueryParams({ contextid: contextid });
But when I press the back-button the browser skips an entry leaving me two pages back.
I.e.
Current situation:
- User starts at Azure DevOps home page
- User navigates to Landing page custom hub
- Hub page renders a table
- User clicks on a table item
- Page changes the address bar and show the detail item
- User clicks back button
- Browser brings user back to Azure DevOps home page
Desired situation:
Browser brings user back to landing page custom hub.
karelkral commented
I met a similar problem. Basically, you must manually work with the browser's history and similarly work with onpopstate when the user clicks the browser's back button. Nothing navigates automatically and this makes sense with plugins.
I am using Url parameter view
for marking the active tab in TabBar, which is similar to your approach.
Basics of my solution:
public async componentDidMount(): Promise<void> {
window.onpopstate = this.onWindowPopState;
}
export enum TabId {
Recent = "Recent",
Builds = "Builds"
}
/** called when user clicks on Back button and state is popped from history */
private onWindowPopState = (event: PopStateEvent) => {
console.log(`onWindowPopState(), event.state=${JSON.stringify(event.state)}`);
const search = event.state ? event.state["search"] : undefined;
if (!search) {
return;
}
const searchParams = new URLSearchParams(search);
const viewId = searchParams.get("view") ?? undefined;
if (viewId !== undefined) {
const parseResult = EnumUtils.tryParse(viewId, TabId);
if (parseResult.success) {
this.setState({
selectedTabId: parseResult.enumValue!
})
}
}
};
private async updateUrlParams(tabId: TabId): Promise<void> {
const existingParams = await this.props.hostNavigationService.getQueryParams();
const viewIdExists = existingParams["view"] !== undefined;
this.props.hostNavigationService.setQueryParams({
view: tabId
});
// Write query params to browsers history https://stackoverflow.com/a/52026044/245460
const state = {
search: "?" + new URLSearchParams({ view: tabId }).toString()
};
// when view is launched for first time, viewId is not set. So replace default history record in this case
if (!viewIdExists) {
console.log("history.replaceState()");
history.replaceState(state, documentTitle);
}
else {
console.log("history.push()");
history.pushState(state, documentTitle);
}
console.log(`history.state=${JSON.stringify(history.state)}, history.length=${history.length}`);
}