Galivan
Galivan

Reputation: 5328

Vue - set v-model dynamically (with a variable containing a string)

I haven't been able to set v-model dynamically.

It works if I type explicitly:

 <div class="form-group mr-3 mb-2">
     <input type="text"  
       v-model="form[filters][firstlastname]" 
     > 
</div>

But I want to loop through an object wherein I have string , like: 'form[filters][firstlastname]'

The parent has the form with properties:

data() {
   return {
     form: new Form({
        filters: {
        gender: [],
        firstlastname: 'My firstlastname'

So, from the parent I pass down the form and filters into the child component, here is filters:

  let formFilters = { filters: [
      {
         type: 'text',
         property: 'form[filters][firstlastname]',        // <-- string 
        placeholder: 'Name',
     },
     {
        type: 'number',
        property: 'paginate', 
        placeholder: 'Max rows'
     },
   ]
}

Child component: (here I loop through the object and generate the input fields)

<div v-for="(filter,index) in formFilters.filters" 
       :key="`${index}_${filter.property}`"
   >
      <input 
         v-if="filter.type === 'text' || filter.type === 'number'"
         :placeholder="filter.placeholder" 
         :type="filter.type"                
          v-model="filter.property"               //<--- set the property
     >

This doesn't work. The v-model just interprets it as a string and not a reference to a form property. I tested other ways, like: v-model="``${[filter.property]}``" (single, not double ```` but it wont show in stackoverflow otherwise) and other crazy things but it isn't valid.

So how do I set v-model with a variable containing a string (so that it can be set dynamically)?

Upvotes: 1

Views: 7887

Answers (1)

Gowthaman
Gowthaman

Reputation: 1282

This is a very tricky problem....

You can access any property present in the data inside html template using 2 ways,

  1. Referring to the property directly
  2. Using $data
data() {
  return {
     firstlastname: 'Mr First last name'
  }
}

so, in html template you can use either
<p>{{firstlastname}}</p> or <p>{{$data.firstlastname}}</p>

For your scenario $data can be used for primitive data types like string or number,

<input 
  v-if="filter.type === 'text' || filter.type === 'number'"
  :placeholder="filter.placeholder"
  :type="filter.type"
  v-model="$data[filter.property]">

But this will not work for your second scenario where you are trying to access nested property of an object form.filters.firstlastname
You can access this property using the following notation $data[form][filters][firstlastname]

In your case, the for loop will result as $data[form.filters.firstlastname] or $data[[form][filters][firstlastname]] which will throw an exception

As suggested in the comments, try different approach or flatten the object. You can refer to this link to see how to flatten the object https://stackoverflow.com/a/25370536/2079271

Upvotes: 7

Related Questions