Skip to content

New feature: Passing props to components from vue-router #973

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

Merged
merged 7 commits into from
Jan 19, 2017
Merged

New feature: Passing props to components from vue-router #973

merged 7 commits into from
Jan 19, 2017

Conversation

bfanger
Copy link
Contributor

@bfanger bfanger commented Dec 2, 2016

@fnlctrl
Copy link
Member

fnlctrl commented Dec 2, 2016

Interesting idea!
/ping @posva @LinusBorg

}

function hasProp (component, prop) {
if (!component.props) {
Copy link
Member

@fnlctrl fnlctrl Dec 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can probably skip this if (!component.props) check since it's already done in https://github.com/bfanger/vue-router/blob/5ad9d480eeed6700a26597484d0c0454d30a13e3/src/util/props.js#L20-L22
Or maybe just inline this function and use the typof expression..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, i've inlined the hasProp function

const propType = component.props[prop].type
if (propType === null || propType === String) {
props[prop] = value
} else if (propType === Number && value.match(/^-?([0-9]+|[0-9]*\.[0-9]+)$/)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably cache this regex literal /^-?([0-9]+|[0-9]*\.[0-9]+)$/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, done

@@ -49,6 +51,7 @@ export default {
matched.instances[name] = undefined
}
}
data.props = resolveProps(route, component, matched.props && matched.props[name])
Copy link
Member

@fnlctrl fnlctrl Dec 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should merge with the original data.props, or it would be a breaking change as the current code disallows explicitly passing props to <router-view>, like <router-view foo="bar"/>

Edit: Sorry, I was wrong about that..

Copy link
Contributor Author

@bfanger bfanger Dec 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The props of <router-view> are still passed to the rendered element. The <div> in Hello still gets the class="view"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did some further testing and setting properties on <router-view> overwrites the values set in data.props, so they are merged somewhere

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that's normal Vue behaviour for any component.

for (const prop in route.params) {
const value = route.params[prop]
if (hasProp(component, prop)) {
const propType = component.props[prop].type
Copy link
Member

@fnlctrl fnlctrl Dec 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about reading prop types at runtime and converting them to Number if possible.. Maybe we should just leave them as string since url params are string by nature. And if Number was supported, should we also support Boolean?

Also, if this type conversion were to be supported, type can be an array, so we'll have to loop over that should it be the case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not ideal, but the alternative was either not to support Number type, or pass it as an string and get a propType warnings and subtle bugs in itemsById.find(item => item.id === id)

I think routing to ID is a common use-case to allow it in the {props: true} scenario

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe in that case, the user should provide a function and convert types by himself. This way we avoid the implicit behavior.

Copy link
Contributor Author

@bfanger bfanger Dec 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've simplified the behavior of the {props: true} which now sets the props to route.params.
Vue complaining about type is much better than silently ignoring some properties and leaving users confused why it doesn't work.

@posva
Copy link
Member

posva commented Dec 3, 2016

I love the idea!
Haven't read all the code yet

@LinusBorg
Copy link
Member

I think this is a really great idea.

/ping @yyx990803 you should check this out, seems very useful!

@yyx990803
Copy link
Member

Looks good! Will review in depth after new year and likely merge when we work on 2.2 for the router.

@@ -1,4 +1,7 @@
// http://nightwatchjs.org/guide#settings-file
var seleniumServer = require('selenium-server');
var chromedriver = require('chromedriver');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is not necessary

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lines are removed

@@ -7,7 +10,7 @@ module.exports = {

'selenium': {
'start_process': true,
'server_path': 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar',
'server_path': seleniumServer.path,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be consistent we should do server_path': require('selenium-server').path instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


### Object mode

When props is an object, this will be set as the component props as-is.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be even better to say when it's useful to pass an object as the props

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've improved the description and code snippet.

@yyx990803 yyx990803 merged commit 2288d83 into vuejs:dev Jan 19, 2017
@yyx990803
Copy link
Member

@bfanger apologies for taking so long to merge this - great work!

@@ -13,6 +13,7 @@
name?: string; // for named routes
components?: { [name: string]: Component }; // for named views
redirect?: string | Location | Function;
props?: boolean | string | Function;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is Boolean | Object | Function in passing-props.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants