diff --git a/README.md b/README.md index 69492ef..f3fce00 100644 --- a/README.md +++ b/README.md @@ -439,7 +439,6 @@ Check out the [Advanced Usage](/Advanced%20Usage.md) documentation for using: - [`routeEvent` event](/Advanced%20Usage.md#routeevent-event) - [`routeLoading` and `routeLoaded` events](/Advanced%20Usage.md#routeloading-and-routeloaded-events) - [Querystring parsing](/Advanced%20Usage.md#querystring-parsing) -- [Static props](/Advanced%20Usage.md#static-props) - [Route transitions](/Advanced%20Usage.md#route-transitions) - [Nested routers](/Advanced%20Usage.md#nested-routers) - [Route groups](/Advanced%20Usage.md#route-groups) diff --git a/Router.d.ts b/Router.d.ts index 1c78760..bd900ea 100644 --- a/Router.d.ts +++ b/Router.d.ts @@ -177,6 +177,9 @@ interface RouterEvent { /** Event type for conditionsFailed */ export type ConditionsFailedEvent = RouterEvent +/** Event type for propsFailed */ +export type PropsFailedEvent = RouterEvent + /** Event type for routeLoading */ export type RouteLoadingEvent = RouterEvent @@ -218,6 +221,7 @@ export default class Router extends SvelteComponent { $on(event: 'routeEvent', callback: (event: CustomEvent) => void): () => void $on(event: 'conditionsFailed', callback: (event: ConditionsFailedEvent) => void): () => void + $on(event: 'propsFailed', callback: (event: PropsFailedEvent) => void): () => void $on(event: 'routeLoading', callback: (event: RouteLoadingEvent) => void): () => void $on(event: 'routeLoaded', callback: (event: RouteLoadedEvent) => void): () => void } diff --git a/Router.svelte b/Router.svelte index 92341a2..c6e3a2e 100644 --- a/Router.svelte +++ b/Router.svelte @@ -579,8 +579,40 @@ const unsubscribeLoc = loc.subscribe(async (newLoc) => { componentParams = null } - // Set static props, if any - props = routesList[i].props + // Set props, if any + props = {} + // Iterate over the props object and resolve any callbacks where applicable + Object.entries(routesList[i].props).forEach(([k, v]) => { + // Catches any errors gracefully which is not handled by the prop function + try { + if (typeof v == 'function') { + const userDefinedPropValue = v(detail.userData) + // resolve if the user provided function returns a promise + if (typeof userDefinedPropValue.then == 'function') { + userDefinedPropValue.then(returnedValue => { + props[k] = returnedValue + }) + } + else { + props[k] = userDefinedPropValue + } + } + else { + props[k] = v + } + + dispatchNextTick('propResolved', { + prop: k, + value: props[k], + }) + } + catch (error) { + dispatchNextTick('propFailed', { + prop: k, + error, + }) + } + }) // Dispatch the routeLoaded event then exit // We need to clone the object on every event invocation so we don't risk the object to be modified in the next tick diff --git a/test/app/src/routes.js b/test/app/src/routes.js index 4e2c816..93f2486 100644 --- a/test/app/src/routes.js +++ b/test/app/src/routes.js @@ -100,7 +100,10 @@ if (!urlParams.has('routemap')) { // This route has a static prop that is passed to it '/foo': wrap({ component: Foo, - props: {staticProp: 'this is static'} + props: { + staticProp: 'this is static', + dynamicProp: async () => Promise.resolve(`this is dynamic - ${new Date}`), + } }), // This component contains a nested router diff --git a/test/app/src/routes/Foo.svelte b/test/app/src/routes/Foo.svelte index 16a186b..61d9584 100644 --- a/test/app/src/routes/Foo.svelte +++ b/test/app/src/routes/Foo.svelte @@ -4,7 +4,15 @@

No static props here!

{/if} +{dynamicProp} +{#if dynamicProp} +

We have a static prop: {dynamicProp}

+{:else} +

No static props here!

+{/if} + \ No newline at end of file diff --git a/test/cases/01-routing.test.js b/test/cases/01-routing.test.js index 7490cfa..b4c37a1 100644 --- a/test/cases/01-routing.test.js +++ b/test/cases/01-routing.test.js @@ -385,4 +385,13 @@ describe(' component', function() { browser.end() }) + + it('dynamic props', (browser) => { + browser + .url(browser.launchUrl + '/#/foo') + .waitForElementVisible('#dynamicprop') + .expect.element('#dynamicprop').text.to.startWith('this is dynamic') + + browser.end() + }) })