BootstrapVue Show Form in Modal

April 9, 2020

Create Form Component with Validation (using vuelidate)

Edit components/PlaceForm.vue

<template>
  <div>
    <b-form ref="form" @submit.prevent="submit">
      <b-form-group
        label="Name"
        label-for="input-name"
        invalid-feedback="Name is required"
      >
        <b-form-input
          :state="validateState($v.item.name)"
          id="input-name"
          v-model="$v.item.name.$model"
        ></b-form-input>
      </b-form-group>

      <b-button type="submit" variant="primary">Submit</b-button>
    </b-form>
  </div>
</template>

<script>
import { validationMixin } from "vuelidate"
import { required, minLength } from "vuelidate/lib/validators"

export default {
  mixins: [validationMixin],
  props: ['item'],
  /*
  data() {
    item: {
      name: 'Desmond'
    },
  },
   */
  validations: {
    item: {
      name: {
        required
      },
    }
  },
  methods: {
    validateState(item) {
      const { $dirty, $error } = item
      return $dirty ? !$error : null
    },
    submit() {
      this.$v.item.$touch()
      if (this.$v.item.$anyError)
        return false

      return this.item
    }
  }
}
</script>

Usage: a table of items, each row have an edit button to show edit form as modal

<template>
  <div>
    <b-table striped hover :items="items" :fields="fields">
      <template v-slot:cell(action)="data">
        <b-button size="sm" variant="outline-primary" @click="showEditPlaceModel(data.index, data.item)">Edit</b-button>>
      </template>
    </b-table>

    <b-modal ref="editPlaceModal" title="Edit Place" @ok.prevent="submitEditPlace">
      <place-form ref="editPlaceForm" :item="editPlace" />
    </b-modal>
  </div>
</template>

<script>
import Vue from 'vue'
import PlaceForm from '~/components/PlaceForm.vue'

export default {
  data() {
    return {
      fields: ['name', 'action'],
      items: [
        { name: 'New York' },
        { name: 'Tokyo' },
        { name: 'Kuala Lumpur' }
      ],
      editPlace: null,
      editIndex: null
    }
  },
  methods: {
    showEditPlaceModel(index, data) {
      // deep clone
      editPlace = JSON.parse(JSON.stringify(data))
      // shallow clone
      // this.editPlace = Object.assign({}, data)
      this.editIndex = index

      this.$refs.editPlaceModal.show()
    },
    submitEditPlace() {
      const data = this.$refs.editPlaceForm.submit()
      if (data) {
        // do something: save data?

        // reactive caveats
        // this.items[this.editIndex] = newData
        Vue.set(this.items, this.editIndex, data)
        this.$nextTick(() => {
          this.$refs.editPlaceModal.hide()
        })
      }
    }
  },
  components: { PlaceForm }
}
</script>
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.