Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJs adding new key to object reference issue

I have an issue when adding a new key to an object and then dynamically modifying the fields associated.

For example add a new column, set column name to "url", then attempt to update the value of url for row 1. In my example the value does not actually update even though the field has v-model="row[field.name]. Is there something I should do to make sure row[field.name] is changed when field.name changes

Code: https://codepen.io/RuttyJ/pen/zdgbPB

 <table>
        <thead>
            <tr>
                  <template v-for="(field, f) in fields">
                      <th>
                          <flex-row>
                              <flex-column style="width: 100%;">
                                  <flex>    
                                      <input type="text" :value="field.name" @input="updateField(f, 'name', $event.target.value)" style="width:100%">
                                  </flex>
                                  <flex style="width: 100%;">
                                      <select :value="field.type"  @change="updateField(f, 'type', $event.target.value)"
                                        style="width:100%">
                                        <option v-for="fieldType in fieldTypeOpts" 
                                          :value="fieldType.value" 
                                          :selected="fieldType.value == field.type">{{fieldType.label}}</option>
                                      </select>
                                  </flex>
                              </flex-column>
                              <flex>
                                  <button @click="removeField(f)" 
                                          style="height:100%;">X</button>
                              </flex>
                          </flex-row>
                      </th>
                  </template>
                  <td>
                      <button @click="newField()">+</button>
                  </td>
            </tr>
        </thead>
        <tbody>
            <tr v-for="(row, r) in rows">
                <td v-for="field in fields">
                    <template>
                        <template v-if="'checkbox' == field.type">
                            <input type="checkbox"                     
                                  style="float:right;"          
                                  v-model="row[field.name]"
                                 >     
                        </template>

                        <input type="number"  
                                v-else-if="'number' == field.type"    
                                style="width:100%"                               
                                :value="row[field.name]"              
                                @input="updateRow(r, field.name, $event.target.value)">

                        <input type="text" style="width:100%"    
                                v-else        
                                v-model="row[field.name]">
                          {{field.name}}
                          <pre>{{field}}</pre>
                         <pre>{{row}}</pre>

                    </template>
                </td>
                <td><button @click="removeRow(r)">X</button></td>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                  <td v-for="(field, i) in fields">

                  </td>
                  <td>
                      <button @click="newRow()">+</button>
                  </td>
            </tr>
        </tfoot>
  </table>

FYI i tried both with v-model and :value/@input

like image 589
Ruttyj Avatar asked Sep 11 '17 21:09

Ruttyj


1 Answers

You are breaking reactivity. You will break reactivity if you modify a property that was not declared when you mount the component. You're trying to directly modify objects in an array that were added later and Vue cannot track that. Because of this, I require all programmers on our team to use this.$set whenever they modify a property on an object.

You can replace:

 this.rows[rowid][fieldName] = value;

with

 this.$set(this.rows[rowid], fieldName, value)
like image 130
For the Name Avatar answered Nov 15 '22 10:11

For the Name