wotamann / vuetify-form-base

Schema-based Form Generator - Vue.js 2.0 Component based on Vuetify 2.0
https://wotamann.github.io/vuetify
232 stars 64 forks source link

How to use v-form-base in a v-for loop? #96

Closed mrpaulharris closed 3 years ago

mrpaulharris commented 3 years ago

I am using in a for loop:

  <v-row justify="center">
    <v-expansion-panels inset>
      <v-expansion-panel
        v-for="(configItem,i) in config.data"
        :key="i"
      >
        <v-expansion-panel-header>{{configItem.id}}</v-expansion-panel-header>
        <v-expansion-panel-content>
          <v-form-base
            :row="{ noGutters: false }"
            :col="{ cols: 12 }"
            :model="configItem"
            :schema="configschema"
            @input="change" 
          />
        <span>{{status}}</span><v-btn type='button' color='primary' class="float-right my-4" @click='save(i)'>Save</v-btn>

        </v-expansion-panel-content>
      </v-expansion-panel>
    </v-expansion-panels>
  </v-row>

How can I pass change event, the index (i) value of the v-for loop, so I can access the correct <v-form-base> element?

I have tried index and id and params, but I just couldn't find a way, eg:

  methods: {
    // set the value of an nested property (path string) in an object. See https://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-and-arrays-by-string-path
    setPath(object, path, value) {
      path.split('.').reduce((o,p,i) => o[p] = path.split('.').length === ++i ? value : o[p] || {}, object)
    },
    // checkbox in vuetify-form-base uses null, instead of false: on change convert null to false
    change({  key, obj, value, id }){ 
      if (obj.schema.type === 'checkbox'){
        this.setPath( this.config[id], key, (value ? true: false) );
      }
    },
wotamann commented 3 years ago

I think you can add your current index from your loop to id

<div v-for="idx in [1,2,6,7 ]" :key="idx" >
    <v-form-base
      :id="'form-base' + idx"
      :model="myModel"
      :schema="mySchema"
      @input="log"
    />
 </div>

....

log({index}) {
 // over index you can select 1,2,6,7
}
mrpaulharris commented 3 years ago

Thank you, that helped me to implement a SAVE function to toggle the button loading and disabled attributes, like this:

<v-form-base
  :id="'form-base' + i"
  :row="{ noGutters: false }"
  :col="{ cols: 12 }"
  :model="configItem"
  :schema="configschema"
  @input="change" 
/>
<v-btn type='button' color='primary' class="float-right my-4" 
:loading="loading[i]" 
:disabled="isdisabled[i]" 
@click='save(i)'>Save</v-btn>

With the change() function defined as

change({ index }){ 
  // this.isdisabled[index[0]] = false; Array updates like this are not reactive, so do this...
  this.$set(this.isdisabled, index[0], false)
},

It took me at least an hour to figure out that updating an array directly is NOT reactive in Vue. The workaround is to use $set() as described in the Vue documentation.

Hope that helps somebody.