# Forms / v-model & 2-Way Binding

# Basic input

Use v-model for two-way binding in forms.

v-model="something"

is like using the combination of:

v-bind:value="something" v-on:input="something = $event.target.value"

# Input:





 










 




<template>
  <div>
    <form>
      <label for="name">Your name</label>
      <input v-model="name" type="text" />
      <p>Your name is: {{ name }}</p>
    </form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: 'Joe Exotic'
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# Output:

Your name is: Joe Exotic

# Form Data as an object

# Input:




 

 








 
 
 
 





<template>
    <div>
      <label for="firstName">First Name: </label>
      <input v-model="user.firstName" type="text"></input><br/>
      <label for="lastName">Last Name: </label>
      <input v-model="user.lastName" type="text"></input><br/>
      <p>Your full name is: "{{user.firstName}} {{user.lastName}}".</p>
    </div>
</template>

<script>
export default {
  data() {
    return {
      user: {
        firstName: '',
        lastName: '',
      },
    };
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# Output:



Your full name is: " ".

# Text Area

What will work is to bind the message with v-model. Line breaks are taken into account but not automatically rendered. You can render line break by using some css.

# Input:





 

 








 
 
 







<template>
  <div>
    <form>
      <label>Type your message :</label>
      <textarea v-model="msg" name="msg"></textarea>
    </form>
    <h5>Message with css white space "pre":</h5>
    <p style="white-space:pre">{{ msg }}</p>
    <h5>Message without extra css:</h5>
    <p>{{ msg }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: `Watch the
line
break`
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# Output:

Message with css white space "pre":

Watch the line break

Message without extra css:

Watch the line break

# Checkbox

The Key to save data from a checkboxes into one array, is to use the same v-model on the input and Vue will bind them into an array.

# Input:





 

 

 



 








 





<template>
  <div>
    <form>
    <label></label>
        <input v-model="bigCats" type="checkbox" id="tiger" name="tiger" value="a tiger">
        <label for="tiger"> I have a tiger</label><br>
        <input v-model="bigCats" type="checkbox" id="puma" name="puma" value="a puma">
        <label for="puma"> I have a puma</label><br>
        <input v-model="bigCats" type="checkbox" id="jaguar" name="jaguar" value="a jaguar">
        <label for="jaguar"> I have a jaguar</label><br>
    </form>
    <p v-if="bigCats.length == 0">Do you have any big cats ?</p>
    <p v-else>I have: <li v-for="bigCat in bigCats"> {{bigCat}}</li></p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      bigCats: [],
    };
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# Output:




Do you have any big cats ?

# Radio Buttons

To save data from radio buttons, use the same v-model on the input.

# Input:





 

 

 












 




<template>
  <div>
    <form>
        <legend>What happen to Don Lewis ?</legend><br/>
        <input v-model="answer" type="radio" value="no">
        <label for="no">She didn't killed him</label><br/>
        <input v-model="answer" type="radio" value="notsure">
        <label for="notsure">I don't know</label><br/>
        <input v-model="answer" type="radio" value="yes">
        <label for="yes">She definitely killed him</label>
    </form>
    <p v-if="this.answer === 'no'">Are you sure ?</p>
    <p v-else-if="this.answer === 'notsure'">I mean...</p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      answer: ""
    };
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# Output:

What happen to Don Lewis ?


# Select / Dropdown

# Input:





 
 
 
 
 








 
 
 
 
 
 





<template>
  <div>
    <form>
      <legend>What is the biggest threat of 2020 ?</legend>
      <select v-model="selectedOption" class="select-css">
        <option v-for="option in options" :value="option.value">
          {{ option.text }}
        </option>
      </select>
    </form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      selectedOption: 'C',
      options: [
        { text: 'Covid-19', value: 'A' },
        { text: 'Murder Hornets', value: 'B' },
        { text: 'Carole Baskin', value: 'C' }
      ]
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# Output:

What is the biggest threat of 2020 ?

# Using modifiers

There are three different modifier in Vue 2.x

# Waiting to complete an input

Use .lazy on v-model to update only when focusing outside of that input

# Input:








 















<template>
  <div>
    <form>
      <p v-if="address">Your address is {{ address }}</p>
      <p v-else>The address will only be updated
      when you click outside of the input field.</p>
      <label for="address">Address of the zoo: </label>
      <input v-model.lazy="address" type="address"></input><br/>
    </form>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      address :''
    };
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# Output:

The address will only be updated when you click outside of the input field.


# Convert input to number

Use .number on v-model to "make sure" the input is of type "number"

# Input:







 



















<template>
  <div>
    <form>
      <p v-if="age">Your age is a {{ ageType }}, it's {{ age }}.
      <p v-else>Your age won't be a string.</p>
      <label for="age">My age: </label>
      <input v-model.number="age" type="number"></input><br/>
    </form>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      age : ''
    };
  },
  computed: {
    ageType: function() {
      return typeof this.age;
    },
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# Output:

Your age won't be a string.


# Trim the input

Use .trim to prevent user to input double or triple white space.

# Input:







 















<template>
  <div>
    <form>
      <p v-if="fullName">Your fullName is {{ fullName }}</p>
      <p v-else>Try typing multiple "space".</p>
      <label for="fullName">FullName: </label>
      <input v-model.trim="fullName" type="fullName"></input><br/>
    </form>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      fullName : 'Joe       Exotic'
    };
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# Output:

Your fullName is Joe Exotic


# Custom input in forms

# Input (Parent Component / Form)








 







 





<template>
  <div>
    <p>Parent</p>
    <p>
      Switched: <strong>{{ dataSwitch }}</strong>
    </p>
    <p></p>
    <SwitchComponent v-model="dataSwitch" />
  </div>
</template>

<script>
export default {
  data: function() {
    return {
      dataSwitch: true
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# Input (Child Component/ Custom input)



 
 





 

 
 
 















































<template>
  <div class="child">
    <div id="on" @click="switched(true)" :class="{ active: value }">On</div>
    <div id="off" @click="switched(false)" :class="{ active: !value }">Off</div>
  </div>
</template>

<script>
export default {
  props: ['value'],
  methods: {
    switched(isOn) {
      this.$emit('input', isOn)
    }
  }
}
</script>

<style scoped>
#on,
#off {
  width: 80px;
  height: 17px;
  background-color: #100d23;
  padding: 10px 3px;
  display: inline-block;
  margin: 19px 12px;
  box-sizing: content-box;
  cursor: pointer;
  text-align: center;
  border-left: 4px solid #202020;
  border-bottom: 2px solid #000000;
}

#on:hover,
#on.active {
  color: #00ff00;
  box-shadow: rgba(0, 255, 0, 1) 0px 0px 6px;
  border: 2px solid #00ff00;
}

#on.active {
  color: #202020;
  background-color: #00ff00;
  box-shadow: rgba(0, 255, 0, 1) 0px 0px 6px;
  border: 2px solid #00ff00;
}

#off:hover,
#off.active {
  background-color: #1e1d45;
  color: white;
  box-shadow: #f09 0px 0px 6px;
  border: 2px solid #f09;
}

#off.active {
  color: #f09;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

# Output:

Parent

Switched: true

On
Off
# See the official Vue.js doc

# Submit a form

Use .prevent for the submit event to no longer reload the page. (It's an event modifiers)

# Input





 














 
 
 




<template>
  <div>
    <form>
      <input type="text" v-model="killer" placeholder="Who killed Jack ?" />
      <button @click.prevent="submitted">Send</button>
    </form>
    <p v-if="isSubmitted">It's {{ killer }}.</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      killer: '',
      isSubmitted: false
    }
  },
  methods: {
    submitted() {
      this.isSubmitted = true
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# Output: