For some reason boolean attributes go completely against the html5 spec:
https://jsfiddle.net/vqm9burf/1/
Since blindly following the spec will break compat, I suggest the following middle-ground:
Any other values should trigger a warning and map to undefined.
[1] Technically, the spec mandates case insensitive comparison. I'm unsure how this would translate to Vue because I believe properties are case sensitive on the javascript end and I don't know how they are handled.
Edit: seems that attribute mapping only works for lowercase properties. As such, case insensitive comparison is acceptable
+1
Note that Vue's prop system has its own semantics and does not aim to map strictly to the HTML attributes semantics.
<div prop> to true and absence of the prop to false.<div prop="prop"> map to true. In HTML5 even if you give a bogus value a boolean attribute will be set to true, e.g. <input type="checkbox" checked="whatever">. The spec's design is imo quite confusing here."true" and "false", I don't think it's necessary to deprecate them simply because the spec doesn't allow it.I disagree with this change, because I think this will create some confusion. It's _prop_, not _attribute_. I like to think that prop always needs to have value, so instead of enabled, I prefer enabled="true". Say, if template is partially rendered on server and if it comes with enabled="some error", I wouldn't want that casted to boolean, I would like to restrict that prop to Boolean only (that's the purpose of "prop assertion"). Also, Vue has some "directive params" that are used without value, e.g. keep-alive, so it will be confusing again.
@yyx990803 Yeah, maybe deprecation is a bit extreme. It was a suggestion within a suggestion (notice the terminating question mark)
@azamat-sharapov which is precisely why I initially proposed that prop="something_except_prop" to trigger a warning and map to undefined. After further consideration (and realizing that browsers don't care about the value too much), I'm going to backtrack on this and say that the presence of the attribute should always bind to true (except when using the old syntax and its value is false). Can you describe a legit use case where you'd want to have a single expression be true/false/string as opposed to using the exception mechanism (be it explicit exceptions, node's (err, value) pair or rust's Option
@za-creature sorry, I am not sure I understand you. What do you mean:
describe a legit use case where you'd want to have a single expression be true/false/string as opposed to using the exception mechanism
When I said "template may partially be rendered on server", I meant something like this:
<div is-admin="<?php isAdmin() ?>">
What if isAdmin() returns error? you want error to be casted to true? Of course you can prevent that error, but It's just simple example, not everybody expert and may make mistake. And I mainly mentioned confusion to be introduced after your proposed changes.
By _legit case_ I meant a piece of code that an average programmer would write for a particular purpose. Maybe I'm an optimist, but I like to believe that the average programmer has more sense than returning an error instead of using the language's built in error handling mechanism (I believe php has two of those). I don't agree that you're doing newbies a favor by tolerating their mistakes: eventually, designing functions that behave that way will get them in trouble (see example below). All modern languages have built-in error handling mechanisms for a reason: things _will_ fail and good code should always _fail safe_. Technically, errors can be propagated but when crossing language barriers (such as php -> html -> js), the propagation needs to be explicit; it's not up to any framework to do that for you unless you ask it to.
And since we're in the realm of confusion, sooner or later, someone will expect regular html components to work with the true/false thing the same way I expected vue to handle boolean attributes as per the html spec:
<input type="checkbox" checked="<?=isChecked()?>">
which would result in a checkbox that's always checked (even when isChecked _returns_ an error).
My proposal attempts to mitigate half of the sources of confusion (with deprecation it would in the long run remove all confusion as vue components would behave the same way html components do)
So, you would want Vue.js props strictly follow HTML spec and prop assertion must support casting, right? If so, I still don't agree with you, it's just my opinion. Let's see what people and maintainer of the framework say. But thank you for detailed explanation!
All modern languages have built-in error handling mechanisms
Yes, but many argue against using exceptions unless absolutely needed.
Try/catch is a very slow operation. Also you lose much context about what
caused the error. Many, including myself, prefer to deal with errors where
they happen.
On Mon, Jun 29, 2015 at 9:09 AM, Azamat [email protected] wrote:
So, you would want Vue.js props strictly follow HTML spec and prop
_assertion_ must support casting, right? If so, I still don't agree with
you, it's just my opinion. Let's see what people and maintainer of the
framework say. But thank you for detailed explanation!—
Reply to this email directly or view it on GitHub
https://github.com/yyx990803/vue/issues/981#issuecomment-116745036.
@mark-hahn I intentionally used _error_ handling as opposed to _exception_ handling in an effort to avoid confusion. Obviously, I have failed. My point was that it is generally better to send errors on a separate channel (as opposed to malloc returning 0 in low memory environments):
(err, values...)Option<T> / Maybe<T>Even when the situation mandates that errors be sent as results, not checking the return code for those special values is equivalent to not handling errors, and one cannot expect a backend-agnostic mvvm-framework to do that for you.
Evan, what has changed now after 31565cc ? I looked at changes, looks like missing prop with Boolean assertion casted to false?
@azamat-sharapov Yes. This should not affect how your write code because undefined is falsy anyway, it simply no longer warns when the prop is expected to be Boolean and missing.
Assuming a prop with Boolean assertion:
<!-- casted to true, no warning -->
<test prop></test>
<!-- casted to false, no warning -->
<test></test>
<!-- treated as string, warning -->
<test prop="prop"></test>
<!-- casted to true, no warning -->
<test prop="true"></test>
Hmm, I thought undefined would be useful, in case prop or value of prop wasn't passed, that could be more logical IMO, because false is false, true is true, undefined is when it's missing. But yeah, not a big deal.
undefined is falsy anyway, I can't see the use case for differentiating a false Boolean property vs an undefined one. If you want to make sure it's provided you can still add required: true.
I meant this kind of case: http://jsfiddle.net/2d3yj5o9/2/
But yes, required: true solves this, didn't realize it, thanks :)
If someone needs to receive undefined for a Boolean prop or a Multi-Type prop that include a Boolean, you can simply set the default value to undefined.
props: {
bu: {
type: Boolean,
default: undefined
}
See my jsfiddle for a comparison of the results for various Boolean props scenarios
https://jsfiddle.net/realcarbonneau/daxs9722/
Most helpful comment
@azamat-sharapov Yes. This should not affect how your write code because
undefinedis falsy anyway, it simply no longer warns when the prop is expected to be Boolean and missing.Assuming a prop with
Booleanassertion: