From 98d1e50c4551f56673b043c8be3dc9613ec674c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Wenzel?= Date: Wed, 18 Oct 2017 13:12:51 +0200 Subject: [PATCH] feat(router): add params to navigate() Adds a `params` to the `navigate()` function, so that ``` router.navigate('#/main/:id/details', undefined, { id: 123, name: "onetwothree" }) ``` results in navigation to ``` '#/main/123/details?name=onetwothree' ``` In other words, found named params are placed in the url, not found ones are added to the querystring. --- src/router.js | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/router.js b/src/router.js index 03844d09..0c60e166 100644 --- a/src/router.js +++ b/src/router.js @@ -1,6 +1,7 @@ import {RouteRecognizer} from 'aurelia-route-recognizer'; import {Container} from 'aurelia-dependency-injection'; import {History, NavigationOptions} from 'aurelia-history'; +import {buildQueryString, parseQueryString} from 'aurelia-path'; import {NavigationInstruction} from './navigation-instruction'; import {NavModel} from './nav-model'; import {RouterConfiguration} from './router-configuration'; @@ -223,12 +224,18 @@ export class Router { * * @param fragment The URL fragment to use as the navigation destination. * @param options The navigation options. + * @param params The parameters to be used when populating the url pattern. */ - navigate(fragment: string, options?: NavigationOptions): Promise { + navigate(fragment: string, options?: NavigationOptions, params?: any): Promise { if (!this.isConfigured && this.parent) { return this.parent.navigate(fragment, options); } + if (params) { + let safeParams = Object.assign({}, params); + fragment = this.applyParams(fragment, safeParams); + } + this.isExplicitNavigation = true; return this.history.navigate(_resolveUrl(fragment, this.baseUrl, this.history._hasPushState), options); } @@ -266,6 +273,39 @@ export class Router { return childRouter; } + /** + * Generates a URL fragment with parameters applied to it. + * + * @param fragment The route fragment whose pattern should have parameters applied to it. + * @param params The route params to be used to populate the route pattern. + * @returns {string} A string containing the generated URL fragment. + */ + applyParams(fragment: string, params: any): string { + let fragments = fragment.split('/'); + let consumed = {}; + for (let i = 0, ilen = fragments.length; i < ilen; ++i) { + let segment = fragments[i]; + + // Try to parse a parameter :param? + let match = segment.match(/^:([^?]+)(\?)?$/); + if (match) { + let [, name, optional] = match; + fragments[i] = params[name]; + consumed[name] = true; + } + } + fragment = fragments.join('/'); + + for (let key of Object.keys(consumed)) { + delete params[key]; + } + let query = buildQueryString(params); + if (query && query.length) { + fragment += (fragment.indexOf('?') < 0 ? '?' : '&') + query; + } + return fragment; + } + /** * Generates a URL fragment matching the specified route pattern. * @@ -496,7 +536,7 @@ export class Router { if (results && results.length) { let first = results[0]; let instruction = new NavigationInstruction(Object.assign({}, instructionInit, { - params: first.params, + params: Object.assign({}, first.params, parseQueryString(queryString)), queryParams: first.queryParams || results.queryParams, config: first.config || first.handler })); @@ -510,7 +550,7 @@ export class Router { } } else if (this.catchAllHandler) { let instruction = new NavigationInstruction(Object.assign({}, instructionInit, { - params: { path: fragment }, + params: Object.assign({ path: fragment }, parseQueryString(queryString)), queryParams: results ? results.queryParams : {}, config: null // config will be created by the catchAllHandler })); @@ -523,7 +563,7 @@ export class Router { let newParentInstruction = this._findParentInstructionFromRouter(router, parentInstruction); let instruction = new NavigationInstruction(Object.assign({}, instructionInit, { - params: { path: fragment }, + params: Object.assign({ path: fragment }, parseQueryString(queryString)), queryParams: results ? results.queryParams : {}, router: router, parentInstruction: newParentInstruction,