Vue

Setting up two-way binding for a component in Vue

Published June 25th, 2019

Important: The information in this article is over 12 months old, and may be out of date or no longer relevant.

But hey, you're here anyway, so give it a read see if it still applies to you.

I’ll be blunt: I am head-over-heels in love with VueJS. It has totally changed my approach to front end development, and increased reusability, while also decreasing development time – and heck, reactive data is bloody awesome.

This one is about binding to a custom component. I’m writing so many components these days, and this is just one little point I guess I overlooked? Assumed? Just didn’t actually consider? Not sure which… but it did lead me to Google.

So I thought I’d share this basic reminder that, even after months developing with VueJS and no doubt having come across this earlier, I’d somehow forgotten to remember for this instance.

Let’s say you’re wanting to make a component, and take advantage of two way binding using v-model when you use your component, as:

1<my-component v-model="data"></my-component>
Copied!

That’s easy, hey – and I definitely remembered that I needed to emit an “input” event to send data from the component back to the “data”, such as:

1this.$emit('input', value);
Copied!

So far, I’ve got my working component that is able to do its internal logic and operations, and then when the certain action is triggered, outputs the current value back to the parent using the $emit call. Brilliant.

But wait… I also need to pass some initial data in to the component too – aka, how do I set a default for my data… aka what do I need to refer to within the component to access what v-model is passing.

That’s a fun thing to try to Google, with such vague phrasing and generic words.

One of the things I love about Vue are the shorthand ways to write things – why use v-bind:prop="value" when I can just use :prop="value"?

It’s less to type, and easier to read. And I know that :prop is passing a property to the component with the set “value”. Easy.

It’s funny to use that example actually, as that’s part of the lesson here.

v-model is a shortcut too – a shortcut for a v-bind, and a v-on.

1<my-component v-model="data"></my-component>
Copied!

is exactly the same as writing

1<my-component v-bind:value="data" v-on:input="data = $event.target.value"></my-component>
Copied!

But seriously, look at the difference in:

  1. readability, and

  2. length of code needed

Which would you pick when writing code? I know my answer, definitely.

v-model is just so much neater to use – and there in lies the key: my component needs to have a prop defined called ‘value’, as that is what v-model is sending as the value to the component.

So a really basic setup for the logic for a component could be:

1{
2 // ...
3 props: {
4 value: {
5 type: String,
6 default: '',
7 required: true
8 }
9 },
10 data: function () {
11 return {
12 data: '' // store the data
13 };
14 },
15 methods: {
16 myOtherOperations: function(){
17 //
18 // perform some other behavior or interaction internally
19 //
20 // when ready, trigger the output.
21 this.output();
22 },
23 output: function () {
24 // pass back to the parent
25 this.$emit('input', this.data);
26 }
27 }
28 // ...
29}
Copied!

When you’re ready, simply call the “output” method and it will emit the “input” for v-model to pick up on.

I just love the magic around this – the in-bound prop of “value” and the out-bound emit of “input” – all succinctly captured in one single property: v-model.

It’s all in the docs – this isn’t anything hidden or ground breaking, and is even something I had read, understood and implemented before when writing some forms-based components – but even with some of the really cool more-advanced stuff I’m doing, the basics sometimes need a prod to the front of memory too.

You may be interested in...