padarom
padarom

Reputation: 3648

VueJS event binding in v-for

I'm displaying a list of objects with VueJS like so:

<div v-for="register in registers">
    <input type="checkbox" v-model="register.isEnabled">
    <input type="text" v-model="register.name" :disabled="!register.isEnabled">

    <span v-if="register.saved">Saved</span>
    <span v-else><a @click="save(register)">Save now</a></span>
</div>

What I'd like to do, is to watch for changes in this object's values and set the saved attribute to false. This is an exemplary version of my Vue instance:

new Vue({
    el: '#app',
    data: {
        registers: [
            { isEnabled: true, name: 'Register 1', saved: true },
            { isEnabled: false, name: '', saved: true },
        ]
    },
    methods: {
        save: function(event) {
            // Save object, set saved to true
        }
    }
});

I've tried settings an onchange listener to the div with the v-for attribute:

<div v-for="register in registers" @change="onChange(register)">

However this only triggers when the first input element is changed (e.g. the checkbox).

Am I able to somehow listen to all changes made to this register object, without having to add a @change event to every single input? If so, how?

Upvotes: 3

Views: 5267

Answers (1)

nils
nils

Reputation: 27215

Am I able to somehow listen to all changes made to this register object, without having to add a @change event to every single input?

This sounds like a pretty reasonable solution actually, especially since the change event doesn't bubble.

I tried to come up with a solution using watch, but since deep watch is not an option for large arrays, it would become pretty messy.

new Vue({
    el: '#app',
    ready: function() {
        this.registers.forEach(function(register, index) {
            this.$watch('registers[' + index + ']', function(newRegister, oldRegister) {
              // Check that it wasn't the `saved` state that changed
              if (newRegister.saved === oldRegister.saved) {
                  newRegister.saved = false;
              }
            });
        });
    },
    data: {
        registers: [
            { isEnabled: true, name: 'Register 1', saved: true },
            { isEnabled: false, name: '', saved: true },
        ]
    },
    methods: {
        save: function(event) {
            // Save object, set saved to true
        }
    }
});

And then you would have to rebind all the watchers in case the registers properties change.

So you're probably easier off just using @change listeners.

Upvotes: 1

Related Questions