234

In VueJS we can add or remove a DOM element using v-if:

<button v-if="isRequired">Important Button</button>

but is there a way to add / remove attributes of a dom element eg for the following conditionally set the required attribute:

Username: <input type="text" name="username" required>

by something similar to:

Username: <input type="text" name="username" v-if="name.required" required>

Any ideas?

roalz
  • 2,699
  • 3
  • 25
  • 42
Don Smythe
  • 9,234
  • 14
  • 62
  • 105
  • 15
    While being not so obvious (hence the confusion) the documentation actually do says that if attribute value evaluates to false then attribute being omitted (https://vuejs.org/v2/guide/syntax.html#Attributes) – AlexanderB Jan 24 '18 at 19:00
  • Actually, the documentation says the attribute won't be added if *“…has the value of `null`, `undefined`, or `false`”*, which is different from a JS script evaluating to false. This means an empty string is falsy in JavaScript, but would still add the attribute to DOM. To prevent that you could try `v-bind:name="name || false"` – Denilson Sá Maia Sep 06 '19 at 14:08
  • @AlexanderB If that's true, how can I pass explicit `false` to child component via a prop? – Bruce Sun Apr 15 '20 at 09:47
  • @BruceSun , If the attribute in context "unintentionally" disappears when you give it false value - try to pass it as a string `'false'`. In other cases when you need to control presence of non-boolean html attribute on the element you can use conditional rendering with `v-if` as suggested here: https://github.com/vuejs/vue/issues/7552#issuecomment-361395234 – AlexanderB Apr 16 '20 at 10:59
  • @AlexanderB I think I have to correct myself - I should say `attribute` but NOT `prop`. We can safely pass explicit `false` via a component property but NOT attribute (which is not recognised as a property). Am I correct? – Bruce Sun Apr 20 '20 at 08:41

12 Answers12

219

Try:

<input :required="test ? true : false">

Update: It has changed in Vue 3, see this answer https://stackoverflow.com/a/64598898

cymruu
  • 2,808
  • 2
  • 11
  • 23
  • 11
    Long form is `` – nathanielobrown May 09 '17 at 14:13
  • 13
    `anythingAtAll : ? true : false` (or `if (condition) { return true; } else { return false; }`) in any language is ... _unseemly_. Just use `return (condition)` or, in this case, `` – Stephen P May 21 '18 at 17:15
  • 6
    if you are sure that variable `test` is `boolean`, you can just use `:required="test"` – tstr Jul 06 '18 at 09:14
  • 2
    Please note that this depends on the component! It's possible that if your property accepts `String` value that by setting it to `false` you will get `type check` error. So set it to `undefined` instead of false. [docs](https://vuejs.org/v2/guide/syntax.html#Attributes) – Traxo Jul 18 '18 at 10:09
  • 4
    using `:required="required"` where `required` is a Boolean component property results in for me – Andrew Castellano Feb 05 '19 at 16:02
  • maybe that's valid? I've always added the attribute the standard way `` – Andrew Castellano Feb 05 '19 at 16:07
  • Having a resulting `required="required"` in your markup is completely normal and standard. You can test this by creating a sample HTML file with a simple `required` attribute. Your browser will fill up the blanks by itself. – pyrsmk Jul 10 '19 at 08:28
  • 3
    Note that this has changed with Vue 3, see one of the answers further down – Connor Shea May 29 '21 at 18:48
  • what if we have to check string like ex: test == 'somestring' then its true else false , then how we do that ? – Ajay Namdev Sep 23 '21 at 06:17
  • @AjayNamdev simply `````` – cymruu Sep 23 '21 at 07:59
94

Conditional rendering of attributes changed in Vue 3. To omit an attribute use null or undefined.

Vue 2:

<div :attr="false">
Result: <div>

<div :attr="null">
Result: <div>

Vue 3:

<div :attr="false">
Result: <div attr="false">

<div :attr="null">
Result: <div>
Jouni Kantola
  • 1,097
  • 7
  • 12
87

Simplest form:

<input :required="test">   // if true
<input :required="!test">  // if false
<input :required="!!test"> // test ? true : false
Syed
  • 15,657
  • 13
  • 120
  • 154
  • 5
    Please note that this depends on the component! It's possible that if your property accepts `String` value that by setting it to `false` you will get `type check` error. So set it to `undefined` instead of false. [docs](https://vuejs.org/v2/guide/syntax.html#Attributes) – Traxo Jul 18 '18 at 10:06
  • @Syed your answer using double exclamation points `!!` I've never seen that syntax before yesterday and during a code review I came across this: -- `` Would you know what `!!!` (3) mean for a `:required` value? Thanks. – Chris22 Aug 10 '18 at 15:52
  • 2
    @Chris22 There is no difference between !test and !!!test, since !!!test is just !!(!test) and because !test is a boolean, !!(!test) is just its double negation, therefore the same. Check this: https://stackoverflow.com/a/25318045/1292050 – Syed Aug 10 '18 at 20:08
  • @Syed thanks. Following your link, [I found this one as well and I agree](https://stackoverflow.com/questions/30895846/falsy-why-should-i-use-instead-of-3-instead-of-1-bang/30895960#30895960). :^) – Chris22 Aug 13 '18 at 16:36
  • What @Syed said isn't untrue – goodson Mar 04 '19 at 21:02
23

<input :required="condition">

You don't need <input :required="test ? true : false"> because if test is truthy you'll already get the required attribute, and if test is falsy you won't get the attribute. The true : false part is redundant, much like this...

if (condition) {
    return true;
} else {
    return false;
}
// or this...
return condition ? true : false;
// can *always* be replaced by...
return (condition); // parentheses generally not needed

The simplest way of doing this binding, then, is <input :required="condition">

Only if the test (or condition) can be misinterpreted would you need to do something else; in that case Syed's use of !! does the trick.
  <input :required="!!condition">

Stephen P
  • 14,422
  • 2
  • 43
  • 67
23

You can pass boolean by coercing it, put !! before the variable.

let isRequired = '' || null || undefined
<input :required="!!isRequired"> // it will coerce value to respective boolean 

But I would like to pull your attention for the following case where the receiving component has defined type for props. In that case, if isRequired has defined type to be string then passing boolean make it type check fails and you will get Vue warning. To fix that you may want to avoid passing that prop, so just put undefined fallback and the prop will not sent to component

let isValue = false
<any-component
  :my-prop="isValue ? 'Hey I am when the value exist' : undefined"
/>

Explanation

I have been through the same problem, and tried above solutions !! Yes, I don't see the prop but that actually does not fulfils what required here.

My problem -

let isValid = false
<any-component
  :my-prop="isValue ? 'Hey I am when the value exist': false"
/>

In the above case, what I expected is not having my-prop get passed to the child component - <any-conponent/> I don't see the prop in DOM but In my <any-component/> component, an error pops out of prop type check failure. As in the child component, I am expecting my-prop to be a String but it is boolean.

myProp : {
 type: String,
 required: false,
 default: ''
}

Which means that child component did receive the prop even if it is false. Tweak here is to let the child component to take the default-value and also skip the check. Passed undefined works though!

<any-component
  :my-prop="isValue ? 'Hey I am when the value exist' : undefined"
/>
 

This works and my child prop is having the default value.

Satyam Pathak
  • 6,612
  • 3
  • 25
  • 52
  • 1
    This is what worked for me when working with select options (and the selected attribute) – Max Mar 29 '21 at 18:08
10

You can add colon before attribute (also can use conditions) like

<div :class="current? 'active': '' " > 
<button :disabled="InvalidForm? true : false " >

If you want to set a dynamic value like props then you also can use colon before attribute name like :

<Child :data="userList" />
Zaheer Alvi
  • 131
  • 1
  • 5
9

It's notable to understand that if you'd like to conditionally add attributes you can also add a dynamic declaration:

<input v-bind="attrs" />

where attrs is declared as an object:

data() {
    return {
        attrs: {
            required: true,
            type: "text"
        }
    }
}

Which will result in:

<input required type="text"/>

Ideal in cases with multiple attributes.

nikk wong
  • 8,059
  • 6
  • 51
  • 68
3

In html use

<input :required="condition" />

And define in data property like

data () {
   return {
      condition: false
   }
}
Nipun Jain
  • 999
  • 6
  • 13
3

You could write something like this:

<input type="text" name="username" :required="condition ? true : false">
VMK053
  • 31
  • 2
2

You can use computed too

<input :required="isRequired" />

Computed:

computed: {
   isRequired () {
      return someLogic //Boolean, true or false
   }
1

use v-bind

v-bind="{ ...(type && { variant: type })

Jeff Voss
  • 3,637
  • 8
  • 46
  • 71
1

In vuejs you have something called v-show which conditionally render the element within the DOM, whereas v-if just won't show on the screen but would still exist on DOM.

You can try this code

use template, don't use the v-show condition within the button attributes

<template v-show="isRequired">
    <button >Important Button</button>
</template>

this "isRequired" seems like its a computed property so make sure you specify the correct logic within that