diff --git a/lib/index.d.ts b/lib/index.d.ts index d477010e..94af2cbd 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -148,6 +148,12 @@ export interface AnyAttrs { [attr: string]: any; } +export interface NavigateOptions { + // Passing this flag to navigate() will cause the matching router handler to execute, but won't update the url + // with the passed fragment. + dontUpdateUrl?: boolean; +} + export class Component< StateT, AttrsT = AnyAttrs, @@ -240,7 +246,7 @@ export class Component< * Executes the route handler matching the given URL fragment, and updates * the URL, as though the user had navigated explicitly to that address. */ - navigate(fragment: string, stateUpdate?: Partial): void; + navigate(fragment: string, stateUpdate?: Partial, navigateOptions?: NavigateOptions): void; /** Run a user-defined hook with the given parameters */ runHook: ( diff --git a/lib/router.js b/lib/router.js index 7cfa52fd..b902c78e 100644 --- a/lib/router.js +++ b/lib/router.js @@ -68,13 +68,17 @@ export default class Router { this.window.history[this.historyMethod] = this.origChangeStateMethod; } - navigate(fragment, stateUpdate = {}) { + navigate(fragment, stateUpdate = {}, navigateOptions = {}) { + const {dontUpdateUrl = false} = navigateOptions; + fragment = stripHash(fragment); if (decodedFragmentsEqual(this.app.state.$fragment, fragment) && !Object.keys(stateUpdate).length) { return; } - stateUpdate.$fragment = fragment; + if (!dontUpdateUrl) { + stateUpdate.$fragment = fragment; + } for (const route of this.compiledRoutes) { const matches = route.expr.exec(fragment); if (matches) { @@ -93,7 +97,7 @@ export default class Router { if (!routeHandler) { throw `No route handler defined for #${fragment}`; } - const routeStateUpdate = routeHandler.call(this.app, stateUpdate, ...params); + const routeStateUpdate = routeHandler.call(this.app, stateUpdate, ...params, navigateOptions); if (routeStateUpdate) { // don't update if route handler returned a falsey result this.app.update(Object.assign({}, stateUpdate, routeStateUpdate)); diff --git a/test/browser/router.js b/test/browser/router.js index 8731d919..a6cf8365 100644 --- a/test/browser/router.js +++ b/test/browser/router.js @@ -150,6 +150,14 @@ describe(`Router`, function () { await nextAnimationFrame(); expect(this.routerApp.textContent).to.equal(`Number: 42`); }); + + it(`does not update url if dontUpdateUrl is passed`, async function () { + expect(window.location.hash).to.equal(``); + this.routerApp.router.navigate(`numeric/42`, {}, {dontUpdateUrl: true}); + await retryable(() => expect(this.routerApp.textContent).to.equal(`Number: 42`)); + expect(this.routerApp.textContent).to.equal(`Number: 42`); + expect(window.location.hash).to.equal(``); + }); }); describe(`replaceHash()`, function () {