Home > Blockchain >  How to use dot delimited string as object path for vue v-model directive
How to use dot delimited string as object path for vue v-model directive

Time:12-06

I have data record

record: {
  address: {
   city: ""
  }
}

array of objects that describe field

fields: [ 
  {
    name: "address.city"
    ...
  }
]

and try to generate form

    <b-field
      v-for="field in fields"
      :key="field.name"
      :label="field.label"
    >
      <b-input v-model="record[field.name]" />
    </b-field>

and get object item with key like address.name I understand that i should pass to v-model record[address][city] but how to do it from dot delimited string?

Is it possible?

CodePudding user response:

const getPathInObject = (path, object) => {
  const [current, ...rest] = path.split('.')
  return rest.length === 0
    ? object[current]
    : getPathInObject(rest.join('.'), object[current])
}

document.write(getPathInObject('a.b.c.d', { a: { b: { c: { d: 'hello' } } } }))
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

EDIT You can try something like this

const getPathInObject = (path, object) => {
  const [current, ...rest] = path.split('.')
  return rest.length === 0
    ? object[current]
    : getPathInObject(rest.join('.'), object[current])
}
const setPathInObject = (path, object, value) => {
  const splitPath = path.split('.')
  let current
  for (
    current = object; 
    splitPath.length > 1; 
    current = current[splitPath.shift()]
  );
  current[splitPath[0]] = value
}

const makeDotSeparatedComputed = path => ({
    [path]: {
    get() { return getPathInObject(path, this)},
    set(v) { setPathInObject(path, this, v) }
  }
})

new Vue({
  el: "#app",
  data: {
    a: { b: { c: { d: 'hello '}}}
  },
  computed: {
    'a.b.c.d': makeDotSeparatedComputed('a.b.c.d')
    }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  Value of a.b.c.d = {{ a.b.c.d }}
   <input v-model="a.b.c.d" /> 
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

I used :value and @input instead v-model. And lodash get and set

      <b-input
        :value="get(data, field.name)"
        @input="set(data, field.name, $event)"
      />

  • Related