Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind query to props with vue-router

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

like image 840
pomber Avatar asked Jun 27 '17 15:06

pomber


People also ask

How do I access my router props?

Another way to access the router props is to add an import statement at the top of the component and import 'withRouter'. import { withRouter } from 'react-router-dom'; Then in the export default statement at the end of the component you would wrap the component in 'withRouter'. export default withRouter(HomePage);

How do I call Vue props?

To specify the type of prop you want to use in Vue, you will use an object instead of an array. You'll use the name of the property as the key of each property, and the type as the value. If the type of the data passed does not match the prop type, Vue sends an alert (in development mode) in the console with a warning.

Can I use props in data Vue?

Using props in VueAfter you have set up the props, you can then use it inside your component as though the data was defined inside the same component. This means you can set up method calls and easily access this.


2 Answers

I 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.

like image 86
Ricardo Nolde Avatar answered Sep 18 '22 18:09

Ricardo Nolde


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 };
    }
}
like image 36
Bruno Zell Avatar answered Sep 21 '22 18:09

Bruno Zell