1

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)?

Galivan
  • 4,842
  • 9
  • 44
  • 76
  • I don't even see how this would work: `v-model="form[filters][firstlastname]" `, shouldn't it be: `v-model="form['filters']['firstlastname']" ` – AT82 Jan 29 '20 at 17:08
  • I guess you're right. But even if I modify it to: `property: 'form[\'filters\'][\'firstlastname\']'`, it's interpreted as a string. I also tried 'form.filters.firstlastname' and it's the same. – Galivan Jan 29 '20 at 17:27
  • Yeah, I know it won't work. But if this is not coming from api, I'd recommend you'd take a different approach to solve this. I don't think this is a good idea in first place? – AT82 Jan 29 '20 at 17:31
  • The filters are defined in the parent (not from api). Well, I can solve it by only adding one property name for each field in my filters object. Then I can say: v-model="form.filters[filter.property]". Then all properties need to be in "form.filters"... I thought it would be nice to have it completely dynamic, but that seems not possible.. – Galivan Jan 30 '20 at 12:48

1 Answers1

5

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

André Kuhlmann
  • 4,378
  • 3
  • 23
  • 42
Gowthaman
  • 1,262
  • 1
  • 9
  • 15