David Tinker
David Tinker

Reputation: 9644

Is it possible to clone a Vuejs property on set?

I have a Vuejs component that edits various properties of its value object and emits an input event with a new object when things change. I don't want to modify the value object itself so I copy properties into data and I have essentially the same code in a watch on value to update them when the value changes.

It would be very much simpler if the value could just be cloned when set. Is there any way to do this? I know I can do this in the "calling" component but it shouldn't have to do that.

Example:

<template>
  <div>
    <v-checkbox label="Indoor" v-model="value.indoor" @change="onChange"/>
    <v-checkbox label="Outdoor" v-model="value.outdoor" @change="onChange"/>
  </div>
</template>

<script>
  export default {
    name: 'OptionsInput',

    props: {
      value: Object, // has indoor, outdoor properties
    },

    methods: {
      onChange() { this.$emit('input', this.value) }
    }
  }
</script>

I don't want to modify value directly.

Upvotes: 1

Views: 2038

Answers (2)

Helder Lucas
Helder Lucas

Reputation: 3353

In the example below when the component instance is created the clone object will retain the initial content of value.

<template>
  <div>
    <v-checkbox label="Indoor" v-model="clone.indoor" @change="onChange"/>
    <v-checkbox label="Outdoor" v-model="clone.outdoor" @change="onChange"/>
  </div>
</template>

<script>
  export default {
    name: 'OptionsInput',

    props: {
      value: Object, // has indoor, outdoor properties
    },

    data () {
       return {
          clone: Object.assign({}, this.value)
       }
    },

    methods: {
      onChange() { this.$emit('input', this.clone) }
    }
  }
</script>

Upvotes: 0

David Tinker
David Tinker

Reputation: 9644

Making a copy via a computed property works. If the value changes then a new copy will be made. Much easier than copying everything into data and having to watch value for changes.

<template>
    <div>
        <label><input type="checkbox" v-model="copy.indoor" @change="onChange"/> Indoor</label>
        <label><input type="checkbox" v-model="copy.outdoor" @change="onChange"/> Outdoor</label>
    </div>
</template>

<script>
    export default {
        name: 'OptionsInput',

        props: {
            value: Object, // has indoor, outdoor properties
        },

        computed: {
            copy() { return  {...this.value} }
        },

        methods: {
            onChange() { this.$emit('input', this.copy) }
        }
    }
</script>

Upvotes: 2

Related Questions