10

In my JavaScript I have:

data: {
    rooms: [
         {type: 'single'},
         {type: 'double'}
         ...
    ],
    selectedSingle: 0,
    selectedDouble: 0,
    ...
},
computed: {
    capitalize: function(string) {
        return string.charAt(0).toUpperCase() + string.slice(1);
    }
}

In HTML I have:

<li v-for="(room, index) in rooms">
    <input type="number" v-model="'selected' + capitalize(room.type)">
</li>

The problem is that I can't find a way to access my models in this way, and the only way I see now is to destroy the v-for and make it manually, but it's not the best solution because I have many "rooms". Any ideas are welcome.

2 Answers 2

21

You are attempting to access a data property via string. For that you can use the object access property notation (obj['propname']) using $data as the object:

<input type="number" v-model="$data['selected' + capitalize(room.type)]">

Plus your computed should really be a method:

  methods: {                                // changed from computed to method
    capitalize: function(string) {

Demo:

new Vue({
  el: '#app',
  data: {
    rooms: [
      {type: 'single'},
      {type: 'double'}
    ],
    selectedSingle: 111,
    selectedDouble: 222,
  },
  methods: {                                // changed from computed to method
    capitalize: function(string) {
      return string.charAt(0).toUpperCase() + string.slice(1);
    }
  }
})
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <ul>
    <li v-for="(room, index) in rooms">
      <input type="number" v-model="$data['selected' + capitalize(room.type)]">
    </li>
  </ul>
</div>

Sign up to request clarification or add additional context in comments.

5 Comments

Works perfect. Exactly what i need. Thanks
Great! Here are the vm.$data api docs for future reference.
@acdcjunior I had the same issue and this helped me! But if I'm honest, I'm not really sure what's going on here. Why is it necessary to use $data? Why doesn't room.type work?
@eysikal $data represents the whole data: { object. This is the only "vue-specific" thing here. Other than that, it's just regular JavaScript property accessing via brackets notation
Ok. I think I understand now. It looks like v-model="" is expecting a raw string, not a variable. So using v-model="room.type" will not not work. I tried binding to v-model as so: :v-model="room.type" - but that also does not work. Using v-model="$data[room.type]" will return the string the from the room.type variable and will set the v-model attribute dynamically, which is what we're after. I'm not entirely clear on why using $data allows us to return the value rather than $data being interpreted as a raw string, but I'm glad this works. Thanks for the help.
2

For people who are using Vue 3, use this instead of $data.

For example:

import { reactive, createApp } from 'vue';

createApp({
  setup() {
    const state = reactive({
      propertyA: 'valueA',
      propertyB: 'valueB',
    });
    return state;
  };
});
<input v-for="p in ['propertyA', 'propertyB']" v-model="this[p]">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.