Vue computed setter with object prop

2.6k views Asked by At

The idea is to pass different objects to an input component, have them displayed there as CSV and be able to edit/validate the text and change the style depending on the validation results. Here is the code I currently have:

<div id="vue">
    <base-input :cslice="c.workspace"></base-input>
</div>

javascript:

(function () {

  Vue.component('base-input', {
    props: ['cslice'],
    data: function () {
      return {
        colors: ['red', 'white', 'yellow', 'green', 'orange', 'purple'],
        ind: 1
      }
    },
    computed: {
      str: {
        get: function () {
          return Object.values(this.cslice).join(", ");
        },
        set: function (val) {
          if(val.indexOf('0'))
            this.ind = Math.floor(this.colors.length * Math.random());
        },
      },
      styleObj: {
        get: function () {
          return { color: this.colors[this.ind] };
        },
        set: function () {

        },
      }
    },
    template: '<div><input v-model="str" :style="styleObj" type="text"/></div>'
  });

  let vue = new Vue({
    el: '#vue',
    data: {
      c: {},
    },
    created: function () {
      this.c = Object.assign({}, this.c, {
        workspace: { width: 820, height: 440 },
      });
    },

  });

})();

Here is the fiddle: https://jsfiddle.net/tfoller/sz946qe2/3/

This code allows me to delete the last character only if the new style is the same as the current, otherwise the text is practically uneditable, how do I fix this problem so I'm able to normally edit the input field?

1

There are 1 answers

0
Dan On

Since the computed in the child uses a prop in its getter, you need to $emit back up a value with the same shape in its setter:

set: function (val) {
   const arrValues = val.split(',').map(v => v.trim());
   console.log(arrValues);
   this.$emit('input', {
      width: arrValues[0],
      height: arrValues[1]
   })
},

That means reversing some of the string formatting stuff you were doing in order to get the right shape.

Listen for that input event in the parent. You can change your prop name to value so that you can use v-model as the listener:

<base-input v-model="c.workspace"></base-input>

Move all of the color changing functionality into a separate method in the child that's triggered by changing the input as well. Here's a demo:

Demo