Skip to content Skip to sidebar Skip to footer

Setting Nested Object Property By String Path

I have 3 select boxes, and I would like them to reset a certain field on select. How can I make it dynamic, so that it is reusable? Here's an excerpt of my code: v-on:select='getDa

Solution 1:

In JavaScript, property accessors do not allow nested object paths, which is what you have in the dot-separated string. By using that string, you're actually creating a property on the root Vue instance instead of setting a nested property, similar to this:

this['form.company.input2'] = ''// XXX: creates `form.company.input2` propthis.form.company.input2 = ''// sets `input2`

To set the object value by path, you could create a method that uses the object path to navigate the current Vue instance's data properties via this:

methods: {
  getDate(url, obj, obj2, event) {
    this.setValue(obj, '')
    this.setValue(obj2[0], '')
    this.setValue(obj2[1], '')
  },
  setValue(path, value) {
    let obj = thisconst parts = path.split('.')
    while (parts.length > 1 && obj.hasOwnProperty(parts[0])) {
      obj = obj[parts.shift()]
    }
    obj[parts[0]] = value
  }
}

newVue({
  el: '#app',
  data() {
    return {
      input1: 'input1',
      form: {
        company: {
          input2: 'input2',
          input3: 'input3'
        }
      }
    }
  },
  methods: {
    getDate(url, obj, obj2, event) {
      this.setValue(obj, '')
      this.setValue(obj2[0], '')
      this.setValue(obj2[1], '')
    },
    setValue(path, value) {
      let obj = thisconst parts = path.split('.')
      while (parts.length > 1 && obj.hasOwnProperty(parts[0])) {
        obj = obj[parts.shift()]
      }
      obj[parts[0]] = value
    },
    route(prop) {
      return prop
    }
  }
})
<scriptsrc="https://unpkg.com/vue@2.6.10"></script><divid="app"><inputv-model="input1"><inputv-model="form.company.input2"><inputv-model="form.company.input3"><button @click="getDate(route('api.v1.get.date'), 'input1', ['form.company.input2', 'form.company.input3'], $event)">
    Reset data
  </button></div>

Alternatively, you could use a library (such as lodash's _.set):

methods: {
  getDate(url, obj, obj2, event) {
    _.set(this, obj, '')
    _.set(this, obj2[0], '')
    _.set(this, obj2[1], '')
  }
}

newVue({
  el: '#app',
  data() {
    return {
      input1: 'input1',
      form: {
        company: {
          input2: 'input2',
          input3: 'input3'
        }
      }
    }
  },
  methods: {
    getDate(url, obj, obj2, event) {
      _.set(this, obj, '')
      _.set(this, obj2[0], '')
      _.set(this, obj2[1], '')
    },
    route(prop) {
      return prop
    }
  }
})
<scriptsrc="https://unpkg.com/lodash@4.17.11/lodash.js"></script><scriptsrc="https://unpkg.com/vue@2.6.10"></script><divid="app"><inputv-model="input1"><inputv-model="form.company.input2"><inputv-model="form.company.input3"><button @click="getDate(route('api.v1.get.date'), 'input1', ['form.company.input2', 'form.company.input3'], $event)">
    Reset data
  </button></div>

Solution 2:

Try to use this.$set function as follows:

this.$set(current,obj,'');
 this.$set(current,obj2[0],'');
 this.$set(current,obj2[1],'');

learn more about that function here

Solution 3:

This library allows you to use nested object paths.

https://www.npmjs.com/package/vue-data-object-path

Your excerpt would look like this:

v-on:select="getDate('{{ route('api.v1.get.date') }}', 'input1', ['form.company.input2', 'form.company.input3'], $event)"

getDate(url, obj, obj2, event){

     let current = this

     current.$op.set(obj, '')
     current.$op.set(obj2[0], '')
     current.$op.set(obj2[1], '')

}

Solution 4:

For getting or setting nested values inside an object having the path as string

functiongetNestedValue(obj, path){
    returnpath.split('.').reduce((o,i)=> o[i] || '', obj)
}

functionsetNestedValue(obj, path, value) {
    let i;
    path = path.split('.');
    for (i=0;i<path.length-1;i++) obj = obj[path[i]];
    obj[path[i]] = value
}

const obj = { a:{ b: [{c: 1 },{ d: 2 }] }}

setNestedValue(obj,'a.b.0.c',3)
console.log(getNestedValue(obj, 'a.b.0.c'))  // 3

Post a Comment for "Setting Nested Object Property By String Path"