Julio Motol
Julio Motol

Reputation: 833

Vuejs - Object notation for refs

I want to group my refs in to an object and access them by object notation. With that in mind, I now have this component:

new Vue({
    el: '#app',
  template: `
    <div>
      <input ref="input.name" type="text"/>
      <input ref="input.email" type="email"/>
      <input ref="input.password" type="password"/>
    </div>
  `,
  created(){
    console.log(this.$refs["input.name"]); // This works fine
    console.log(this.$refs.input.name); // throws "TypeError: Cannot read property 'name' of undefined"
  }
})

But it only shows this:

{
    input.name: input,
    input.email: input,
    input.password: input,
}

What I want is something like this:

{
    input: {
        name: input,
        email: input,
        password: input,
    },
}

Check fiddle here

Update:

I'm well aware of v-model but that's not what I need, I'll be doing something else with DOM.

Upvotes: 0

Views: 406

Answers (2)

dr_barto
dr_barto

Reputation: 6085

This cannot work: refs only support strings as keys (see the docs), so there is not way of using objects here.

Also, a string with "dot notation" does not magically transform into an object with a nested property -- it's just a string. You could work around this by manually parsing the ref strings into an object structure, as has been demonstrated by @Ilia Brykin's answer. But I honestly think that you are misunderstanding the purpose of the whole ref system if you really want to do that.

P.S.: If you drop the "dort notation" part, you could use keys like input_name and access them via this.$refs.input_name.

EDIT

Another idea: you can get all input refs by their common prefix.

Object.keys(this.$refs).filter(ref => ref.startsWith('input.')

This gives you an array of ref strings of input elements.

Upvotes: 1

Ilia Brykin
Ilia Brykin

Reputation: 271

new Vue({
  el: '#app',
  data() {
    return {
      inputs: {}
    }
  },
  template: `
    <div>
      <input ref="input.name" type="text" value="123"/>
      <input ref="input.email" type="email"/>
      <input ref="input.password" type="password"/>
      <button type="button" @click="clickMe">Click ME</button>
    </div>
  `,
  mounted() {
    this.setRefs();
    console.log("this.inputs", this.inputs);
  },
  methods: {
    setRefs() {
      const INPUTS = {};
      for (key in this.$refs) {
        if (key.indexOf(".")) {
          const KEYS_LIST = key.split(".");
          INPUTS[KEYS_LIST[0]] = INPUTS[KEYS_LIST[0]] || {};
          INPUTS[KEYS_LIST[0]][KEYS_LIST[1]] = this.$refs[key];
        }
      }
      this.inputs = INPUTS;
    },
    
    clickMe() {
      console.log("this.inputs.input.name.value", this.inputs.input.name.value);
    },
  },
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

Upvotes: 1

Related Questions