Finally, the day has come, to understand the missing piece of the puzzle, data binding. So far, we have seen how to use interpolations, v-bind
for attribute binding and v-on
to listen to events. The missing piece was v-model
which is used for two-way data binding and this is exactly what we will be concentrating on today!
Big word alert!
Two-way data binding: This is just a relation between the model (data
object in the Vue instance) and the view. Any change made in the view (say, by the user) will immediately be reflected in the underlying Vue model and will be updated at all places where this data is being rendered in the view. In other words,
- View is updated with the change made to the data property (model)
- And, the data property (model) is updated whenever a change is made in the view
Is your head spinning yet? No worries! We will understand this concept by walking through an example.
v-model directive
This two-way binding is usually created with form inputs and controls. And v-model
is the directive used to achieve just that! To be more specific, below are the exact HTML elements with which v-model
is used,
<input>
<textarea>
<select>
- Components (we will be covering this topic in the “Advanced VueJS” section)
Example walkthrough
Let us take an example with <input>
element to show a text field on the webpage. Let us also have a “message” property in the Vue instance’s data
object which acts as our Vue model and a <p>
tag to render the value using mustache syntax (text interpolation). Now, we want to,
- Populate the text field with the
message
property’s value, say, “hi” i.e., updating the view with the model. - Whenever the value, “hi” is changed by the user in the text field, it has to be updated in the data property,
message
in our case i.e., updating the model with changes in view and - Also rendering it in the
<p>
tag simultaneously
All these three steps can be done by adding the v-model
directive to the <input>
tag and binding the “message
” property to it like so,
<input type="text" v-model="data_property_to_bind"></input>
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Hello Vue!</title>
<!-- including Vue with development version CDN -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h2>Welcome</h2>
<div>
<!-- two-way binding with v-model -->
Greeting Message:
<input type="text" v-model="message"></input>
<p>The message is: {{ message }}</p>
</div>
</div>
<!-- including index.js file -->
<script src="index.js"></script>
</body>
</html>
Index.js
new Vue({
el: "#app",
data: {
message: "hi"
}
});
So, the v-model
directive tells vue.js to set up a two-way binding for the input field and the message
data property mentioned within the quotation marks. All this happens reactively of course!
The initial output is as below.
The right half in the image shows Vue DevTools pane. The data
object with the message
property and its value can also be seen.
As we change the message in the text field from “hi” to “hello”, with every character that we type, it will reactively get updated in the underlying data model (shown in the Vue Devtools) and updated in the view where we output using mustache syntax in the <p>
tag.
I highly recommend you to open Vue Devtools as shown in the image and change the value in the text field to see this change happening reactively. It will be a feast to your eyes! I can assure that.
Modifiers
v-model comes with three modifiers. In case you missed the modifiers part, check this out.
Usage: Following the v-model
directive, add a dot and specify the modifier.
.lazy
– sync the input with the data after change events instead of input events
<input v-model.lazy="message">
.number
– used to cast valid input string to numbers
<input v-model.number="age">
.trim
– to trim the user input automatically
<input v-model.trim="message">
The code is available in the GitHub repo as always.
Play around with that and notice how Vue correctly updates the element based on whether the input type is a text field, checkbox, radio button, select, multi-select, text area element and so on… It looks and sounds magical because all the syntax sugar you need to achieve this elephant-sized task is a single directive, v-model
. Feel free to give a shout out in the comments section in case you bump into any issues.
Have a great day ahead!
I have a issue with using v-model on a input of type ‘text’. The binding only works one way, what is written on the input gets set on the parameter but if the parameter is changed the input value doesn’t.
I’ve tried passing the value with ‘v-bind:value’ but that creates a conflict issue with v-model.
Hi Bruno,
Please could you share the code that was tried? I will be able to answer your question and provide a solution.
This is surely a very good blog, thanks a lot for sharing such nice information here.
Thank you Priya and I am happy it is helping you.