Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add dynamic props #283

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions Router.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ interface RouterEvent<T> {
/** Event type for conditionsFailed */
export type ConditionsFailedEvent = RouterEvent<RouteDetail>

/** Event type for propsFailed */
export type PropsFailedEvent = RouterEvent<RouteDetail>

/** Event type for routeLoading */
export type RouteLoadingEvent = RouterEvent<RouteDetail>

Expand Down Expand Up @@ -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
}
36 changes: 34 additions & 2 deletions Router.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -579,8 +579,40 @@ const unsubscribeLoc = loc.subscribe(async (newLoc) => {
componentParams = null
}

// Set static props, if any
yaameen marked this conversation as resolved.
Show resolved Hide resolved
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
Expand Down
5 changes: 4 additions & 1 deletion test/app/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ if (!urlParams.has('routemap')) {
// This route has a static prop that is passed to it
yaameen marked this conversation as resolved.
Show resolved Hide resolved
'/foo': wrap({
component: Foo,
props: {staticProp: 'this is static'}
props: {
staticProp: 'this is static',
dynamicProp: async () => Promise.resolve(`this is dynamic - ${new Date}`),
yaameen marked this conversation as resolved.
Show resolved Hide resolved
}
}),

// This component contains a nested router
Expand Down
8 changes: 8 additions & 0 deletions test/app/src/routes/Foo.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@
<p>No static props here!</p>
{/if}

{dynamicProp}
{#if dynamicProp}
<p>We have a static prop: <b id="dynamicprop">{dynamicProp}</b></p>
{:else}
<p>No static props here!</p>
{/if}

<script>
// Static props if they're set
export let staticProp = null
export let dynamicProp = null
</script>
9 changes: 9 additions & 0 deletions test/cases/01-routing.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,4 +385,13 @@ describe('<Router> 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()
})
})