Skip to content
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

Binding boolean attributes have unexpected result in vue-next #1173

Closed
Yukon123 opened this issue Aug 13, 2021 · 6 comments
Closed

Binding boolean attributes have unexpected result in vue-next #1173

Yukon123 opened this issue Aug 13, 2021 · 6 comments
Assignees

Comments

@Yukon123
Copy link

Yukon123 commented Aug 13, 2021

Hi there.

My confusion lies in the following two points :

​ 1.Readonly is a boolean attributes,but didn't performs like the Docs present.

​ 2.Checked is a boolean attributes,Although its value is true, it is still not mounted in html element.

Ps: The following example is run in the Vue3 environment.

The Vue3 docs says :

In the case of boolean attributes, where their mere existence implies true, v-bind works a little differently. For example:

<button v-bind:disabled="isButtonDisabled">Button</button>

The disabled attribute will be included if isButtonDisabled has a truthy value. It will also be included if the value is an empty string, maintaining consistency with <button disabled="">. For other falsy values the attribute will be omitted.

Another description of binding boolean attributes is

but it just about treating enumerated attributes as normal non-boolean attributes,and no refer to this issue.

MDN says

Some content attributes (e.g. required, readonly, disabled) are called boolean attributes.

In My Test

​ If the readonly have falsy values like 0 , -0 , NaN , It will also be included.

    <input :readonly="0" placeholder="0" />
    <input :readonly="-0" placeholder="-0" />
    <input :readonly="NaN" placeholder="NaN" />

​ Result in browsers

    <input readonly placeholder="0" />
    <input readonly placeholder="-0" />
    <input readonly placeholder="NaN" />

​ The other example in boolean attributes (e.g. required, disabled) were perform just like the doc present ,the attribute will be omitted with falsy values(exclude empty string) .

Another example

    <input type="radio" :checked="true"  ref="r1" @click="tapRadio" />
    <input type="radio" :checked="false" ref="r2" @click="tapRadio" />
 tapRadio() {
      console.log(this.$refs.r1.hasAttribute('checked'))   //false  --->  expect true
      console.log(this.$refs.r2.hasAttribute('checked'))   //false  
    },

In the views it's correct,it shows one radio is checked and the other is unchecked.

But in element there has no attribute called 'checked'.

    <input type="radio" />
    <input type="radio" />
@NataliaTepluhina
Copy link
Member

@Yukon123 I noticed that you refer to Vue 2 docs here, just to make sure: what version of Vue you are using in the examples above? Attribute coercion behavior changed in Vue 3, here is an overview: https://v3.vuejs.org/guide/migration/attribute-coercion.html#attribute-coercion-behavior

@Yukon123
Copy link
Author

Yukon123 commented Aug 13, 2021

@Yukon123 I noticed that you refer to Vue 2 docs here, just to make sure: what version of Vue you are using in the examples above? Attribute coercion behavior changed in Vue 3, here is an overview: https://v3.vuejs.org/guide/migration/attribute-coercion.html#attribute-coercion-behavior

@NataliaTepluhina Thanks a lot. I reading Vue3 document but test in Vue2 environment.That its why my confuse happened. Thanks again for point that.

@Yukon123 Yukon123 reopened this Aug 13, 2021
@Yukon123 Yukon123 changed the title Binding boolean attributes have unexpected result Binding boolean attributes have unexpected result in vue-next Aug 13, 2021
@Yukon123
Copy link
Author

@Yukon123 I noticed that you refer to Vue 2 docs here, just to make sure: what version of Vue you are using in the examples above? Attribute coercion behavior changed in Vue 3, here is an overview: https://v3.vuejs.org/guide/migration/attribute-coercion.html#attribute-coercion-behavior

@NataliaTepluhina I have changed my operating environment to Vue3.Still, there are some strange things happened on binding boolean attributes.In that case,I edit and reopen the issue.I would be very grateful if you could check it out.

@skirtles-code
Copy link
Contributor

When setting the attributes of a DOM element, Vue first checks whether there is a property on the element with the same name as the attribute. If there is, it will assign the value to the property rather than the attribute. In some cases, the browser will update the attribute when the property is assigned. In other cases, such as checked, this doesn't happen.

For most attributes it won't matter, as setting the property achieves the desired result. If you need to force the creation of an actual attribute you can use ^checked instead of :checked. This is new in Vue 3.2 and the ^ is a short-hand for v-bind with the .attr modifier. In practice, you would use v-model instead of checked anyway.

The problem with readonly is separate. There are a few boolean attributes that need to be handled specially because their corresponding property names are slightly different from their attribute names. readonly is one such example, where the property is called readOnly. The problem you're seeing with 0 not being treated as falsy is caused by this separate code path.

I've got a fix for this locally. I still need to update the SSR handling but once I've got that working I'll put in a PR.

@skirtles-code skirtles-code self-assigned this Aug 14, 2021
@Yukon123
Copy link
Author

Yukon123 commented Aug 14, 2021

When setting the attributes of a DOM element, Vue first checks whether there is a property on the element with the same name as the attribute. If there is, it will assign the value to the property rather than the attribute. In some cases, the browser will update the attribute when the property is assigned. In other cases, such as checked, this doesn't happen.

For most attributes it won't matter, as setting the property achieves the desired result. If you need to force the creation of an actual attribute you can use ^checked instead of :checked. This is new in Vue 3.2 and the ^ is a short-hand for v-bind with the .attr modifier. In practice, you would use v-model instead of checked anyway.

The problem with readonly is separate. There are a few boolean attributes that need to be handled specially because their corresponding property names are slightly different from their attribute names. readonly is one such example, where the property is called readOnly. The problem you're seeing with 0 not being treated as falsy is caused by this separate code path.

I've got a fix for this locally. I still need to update the SSR handling but once I've got that working I'll put in a PR.

Thanks for the reply,the checked behavior just like what you describe ,i recklessness miss that part description in the docs.the
readonly aslo matches your description .Looking forword to you PR.

@skirtles-code
Copy link
Contributor

This should now be fixed. readonly should be behaving like other boolean attributes as of Vue 3.2.3. Thanks for reporting the issue.

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

No branches or pull requests

4 participants
@NataliaTepluhina @skirtles-code @Yukon123 and others