Is it possible to bind query values to props declaratively?
I want /my-foo?bar=my-bar
to pass the props {foo: "my-foo", bar: "my-bar"}
.
I'm currently using something like this:
export default new Router({
routes: [
{
path: "/:foo",
name: "Foo",
component: FooPage,
props: route => ({ foo: route.params.foo, bar: route.query.bar})
}
]
});
And I'm looking for something like:
export default new Router({
routes: [
{
path: "/:foo?bar=:bar",
name: "Foo",
component: FooPage,
props: true
}
]
});
I'm using vue-router 2.3.1
Is it possible to bind query values to props declaratively?
I want /my-foo?bar=my-bar
to pass the props {foo: "my-foo", bar: "my-bar"}
.
I'm currently using something like this:
export default new Router({
routes: [
{
path: "/:foo",
name: "Foo",
component: FooPage,
props: route => ({ foo: route.params.foo, bar: route.query.bar})
}
]
});
And I'm looking for something like:
export default new Router({
routes: [
{
path: "/:foo?bar=:bar",
name: "Foo",
component: FooPage,
props: true
}
]
});
I'm using vue-router 2.3.1
Share Improve this question asked Jun 27, 2017 at 15:07 pomberpomber 24k15 gold badges82 silver badges96 bronze badges 2 |2 Answers
Reset to default 12I don't understand the problem with your current approach; solves your use case just fine.
That said, you could try Object.assign
, something like this:
export default new Router({
routes: [{
path: "/:foo?bar=:bar",
name: "Foo",
component: FooPage,
props: route => Object.assign({}, route.query, route.params)
}]
})
... you can also try a more modern approach by using object spread (if you have babel correctly configured) ...
route => ({ ...route.query, ...route.params })
Having route.params
as the last merged/spread item avoids having querystrings overriding path parameters.
I am not aware of any declarative directive for that, but I do like Ricardos general approach. What might be a problem with that is that it unconditionally binds all query parameters as a prop, so one can modify any predefined props of that component just by adding it to the url.
If you want a filter and still reusability, you can define a helper function and bind the query in a less verbose way:
import bindQuery from "./router-query-bind";
export default new Router({
routes: [{
name: "Foo",
path: "/:foo",
props: bindQuery(["bar"]), // only binds 'bar' from query as a prop
component: FooPage
}, {
name: "Bar",
path: "/:bar",
props: bindQuery(), // binds all query parameters as a props
component: BarPage
}]
});
With an implementation like the following. Note that this is TypeScript and has type annotations. Just remove them if you need plain JavaScript.
import { Route } from "vue-router";
type RoutePropsFunction = (route: Route) => Object;
/**
* Creates a props-function for Vue-Router to pass all route parameters and query parameters as
* props to the routed component.
* You may filter the passed query parameters by name so that only the expected
* props will be bound.
* @param queryFilter List of query parameters which will be passed as props to the component.
* This is optional. If not set all query parameters will be bound.
*/
export default function (queryFilter?: string[]): RoutePropsFunction {
return function (route: Route) {
const filtered = queryFilter ?
queryFilter.reduce((a, b) => ({ ...a, [b]: route.query[b] }), {}) :
route.query;
return { ...route.params, ...filtered };
}
}
path-to-regexp
for its path matching. Their documentation states: "The RegExp returned by path-to-regexp is intended for use with pathnames or hostnames. It can not handle the query strings or fragments of a URL." – thanksd Commented Jun 29, 2017 at 21:25mounted
of the component? – maxpaj Commented Jun 10, 2018 at 14:05