-
Notifications
You must be signed in to change notification settings - Fork 546
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
Proposal for dynamic directive arguments #4
Conversation
How this proposal affects custom directives? Would |
@henriqemalheiros custom directive would receive the evaluated argument I think - which requires no change in implementation. Is there a valid use case where the directive would want access to the raw argument expression? |
@yyx990803 not the raw argument expression. I meant, if the argument is updated, how will the custom directive know about it? Take for instance this overly simple directive that shows an alert: Vue.directive('alert', {
bind(el, { arg, value }) {
if (![ 'click', 'mouseover' ].includes(arg)) {
throw new Error('incorrect directive argument')
}
el.__alertValue = value
el.__alertCallback = () => {
window.alert(el.__alertValue)
};
el.addEventListener(arg, el.__alertCallback)
},
update(el, { value, oldValue }) {
if (value !== oldValue) {
el.__alertValue = value
}
}
}) If the user changes the argument from |
I think above is a use case to access raw argument expression, that way a directive can choose to throw an error if a dynamic argument is used. Or |
Wouldn't dynamic ones unbind and bind again? |
@henriqemalheiros I see what you mean now, yes, dynamic argument does introduce an extra change point to watch for in custom directives. I'll update the RFC to reflect that. |
In general, I like it. It's quite concise and applies to different directives with the same syntax. One thing worth mentioning is that people coming from Angular might be thrown off by this, as One alternative could be using
The biggest benefit is that single With that said, do we know how to achieve dynamic attribute names in other framework that could be used as a mental reference? I can't seem to find anything for neither Angular, Aurelia nor Ember. |
I like the proposal. 🙂 I don't have any strong opinions on what kinds of expressions should be allowed, but it might be useful to only officially support simple property expressions (like what @laander I agree it's good to consider people coming from other frameworks, but I think it's better to be consistent with JavaScript in general, where |
One potential downside is that this feature may lead to the assumption that any JavaScript expression can be used inside the |
@chrisvfritz That's the winning argument for @Justineo Good point, but perhaps that's a saviour in disguise: inline interpolation of slot name should as a minimum be discouraged (use computed properties instead) and even better if the compiler won't accept it as valid. IMO opinionated decisions on fringe use cases like this are where Vue shines. |
Which does not work as expected. A workaround would be: | ||
|
||
``` html | ||
<div :[`key${foo}`]="value"></div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<div :[`key${foo}`]="value"></div> | |
<div :[`${key}foo`]="value"></div> |
Scott
Just so I am certain I do understand, is this valid? <!-- v-slot with dynamic name -->
<foo>
<template v-slot:[object.propName]>
Hello
</template>
</foo> Scott |
What would be the behaviour of <div v-on:[event]="handler"></div> with null/undefined value of <template>
<div v-on:[conditionalClick?'click':null]="handler"></div>
<div v-on:[conditionalClick&&'click']="handler"></div><!-- if we allow false -->
</template> or <template>
<div v-on:[conditionalClick]="hander"></div>
</template>
<script>
export default {
computed: {
conditionalClick () {
return isMonday() ? 'click' : null
}
}
}
</script> Of course that could apply also to |
@smolinari yes, that's valid. As long as the expression does not contain characters that causes the HTML parser to end parsing of an attribute name - i.e. space and quotes. |
@jacekkarczmarczyk that's an interesting point. I'm inclined to allow falsy values to indicate that the binding should be ignored/removed. The concern would be it silently lead to undesired behavior when the falsy value is passed mistakenly. |
@jacekkarczmarczyk on a second thought, unfortunately if we generate the code like the following: on: {
[null]: handler
}
Generating extra code to check the dynamic value type will resulting in less efficient code, but maybe it's worth it since dynamic argument is probably not a very commonly used feature. |
We pretty much have 3 options regarding falsy/non-string values:
|
@yyx990803 Re: 3 - Wouldn't |
@jacekkarczmarczyk |
As mentioned in #4 (comment), I don't think we should allow arbitrary JavaScript expressions inside I agree with @chrisvfritz that maybe we should only allow what v-model's value allows in the |
@Justineo in the updated proposal I mentioned we can actually detect unintentional spaces/quotes in directive arguments at the parser level, so if the user accidentally cause the dynamic argument attribute to terminate early, they will get appropriate warning. Do you still think it's necessary to limit the expression in that case? Btw the reason |
I just tend to put DSL syntax into the attribute name while leaving JavaScript expressions with full expressive power to the attribute value. In that way we won't have to write space-less JavaScript code and It's also easier for tooling. Is there any chance that we move the dynamic part into the attribute values? I've been thinking about this but haven't come up with something neat enough yet. |
@Justineo I am in general against adding artificial restrictions when we don't have technical reasons to do so. Watch expressions are limited because we don't want to implement a full expression parser - that's a tradeoff due to technical constraint. Dynamic arguments are just placed into generated code and handled by the JS engine. The only technical restriction here is attribute name characters. |
ee8bfa8
to
6a0b7be
Compare
Updated: added section regarding handling of This RFC is now in final comment period. |
@yyx990803 "Unresolved questions" section could be removed i guess |
@yyx990803 - for my understanding once more, will this be possible too? <foo>
<template :slot:[name]>
<-- stuff to fill the dynamically named slot with... -->
</template>
</foo> or maybe Scott |
@smolinari It will be |
@Justineo - Ok. But, Scott |
As I understand, this proposal is exactly originated from the problem that dynamic slot names doesn't fit into our current directive syntax after we merged |
True, but that has nothing to do with leaving
reads Bind as namedSlot with someProps. And....
reads Bind as dynamic slotName with someProps. I'll leave it at that. I don't want to muddy the discussion further. Just a yea or nay from Evan will be fine, maybe with a short explanation why it's a bad idea or not possible or maybe it is possible? 😁 Scott |
@smolinari the main problem is consistency: |
@yyx990803 - Thanks. Makes sense, Is there somewhere I can DM you an idea along these lines? Scott |
@smolinari why not make an RFC? The process is designed to help you think through rough ideas. |
Nevermind. I did what you said Evan and was writing down my thoughts in an issue here and then realized I couldn't come up with a decent example to make the suggestion worth while. 😁 Scott |
Full rendered proposal