Search code examples
javascriptvue.jsbootstrap-modalbootstrap-vue

Cannot set reactive property on undefined, null, or primitive value bootstrap Vue modal


please I need help with this error, app.js:108639 [Vue warn]: Cannot set reactive property on undefined, null, or primitive value: .

I'm working with bootstsrap vue modal and having this error. Here is my code snippet below

Firstly here is my template snippet

<div class="card-tools">
    
  <b-button class="btn btn-success" v-b-modal.modal-prevent-closing>
    Add Staff
    <i class="fas fa-user-plus fa-fw"></i>
  </b-button>

  <b-modal
    id="modal-prevent-closing"
    ref="modal"
    title="Enter Staff Info"
    @show="resetModal"
    @hidden="resetModal"
    @ok="handleOk"
  >
    <form ref="form" @submit.stop.prevent="handleSubmit">
      <b-form-group
        label="Name"
        label-for="name-input"
        invalid-feedback="Name is required"
        :state="nameState"
      >
        <b-form-input
          id="name-input"
          v-model="info.name"
          :state="nameState"
          required
        ></b-form-input>
      </b-form-group>
      <b-form-group
        label="Email"
        label-for="email-input"
        invalid-feedback="Email is required"
        :state="emailState"
      >
        <b-form-input
          id="email-input"
          v-model="info.email"
          :state="emailState"
          required
        ></b-form-input>
      </b-form-group>
      <b-form-group
        label="Phone"
        label-for="phone-input"
        invalid-feedback="Phone is required"
        :state="phoneState"
      >
        <b-form-input
          id="phone-input"
          v-model="info.phone"
          :state="phoneState"
          required
        ></b-form-input>
      </b-form-group>
      <b-form-group
        label="Job Title"
        label-for="job_title-input"
        invalid-feedback="Job title is required"
        :state="phoneState"
      >
        <b-form-input
          id="phone-input"
          v-model="info.job_title"
          :state="job_titleState"
          required
        ></b-form-input>
      </b-form-group>
      
    </form>


</div>

Now here is my script

import { BButton, BModal, VBModal } from "bootstrap-vue";

export default {
    
    components: {
        BButton,
        BModal
    },
    
    directives: { 
        'b-modal': VBModal 
    },
    
    data() {
        return {
            staffs: {},
            nameState: null,
            emailState: null,
            phoneState: null,
            job_titleState: null,
            
            info: {
                name: '',
                email: '',
                phone: '',
                job_title: ''
            },
            
            showModal: false
        }
    },

    methods: {
        getStaffs() {
            axios.get("api/user").then(({data }) => (this.staffs = data));
        },
        // createStaff () {
        // this.form.post('api/user')
        //     .then(({ data }) => { console.log(data) })
        // },
        checkFormValidity() {
            const valid = this.$refs.form.checkValidity()
            this.nameState = valid
            return valid
        },
        resetModal() {
            this.info = ''
        },
        handleOk(bvModalEvt) {
            // Prevent modal from closing
            bvModalEvt.preventDefault()
            // Trigger submit handler
            this.handleSubmit()
        },
        handleSubmit() {
            // Exit when the form isn't valid
            if (!this.checkFormValidity()) {
                // return 
                console.log(this.info)
            }
            // Hide the modal manually
            this.$nextTick(() => {
              this.$bvModal.hide('modal-prevent-closing')
            })
        }
    },
    
    created() {
        this.getStaffs();
    },
    
    mounted() {
        console.log('Component mounted.')
    }

};

I just wanted to be sure my code is correct before doing the validation. Thanks in advance


Solution

  • I tried to implement your code into a snippet, and there is one thing with your code that causes an error. It's because you are setting this.info to an empty string, not the object that already is in the data property.

    Also, check your b-vue version, which you are using. It may cause warning issues.

    I tried not to change your code and simulate your issue as I could understand. Please let me know If I wrote the code with the wrong purpos

    new Vue({
      el: "#app",
      data: function() {
        return {
          staffs: {},
          nameState: null,
          emailState: null,
          phoneState: null,
          job_titleState: null,
    
          info: {
            name: '',
            email: '',
            phone: '',
            job_title: ''
    
          },
    
          showModal: false
        }
      },
      methods: {
        getStaffs() {
          this.staffs = {}
        },
        checkFormValidity() {
          const valid = this.$refs.form.checkValidity()
          this.nameState = valid
          return valid
        },
        resetModal() {
          this.info = {
            name: '',
            email: '',
            phone: '',
            job_title: ''
    
          }
        },
        handleOk(bvModalEvt) {
          // Prevent modal from closing
          bvModalEvt.preventDefault()
          // Trigger submit handler
          this.handleSubmit()
        },
        handleSubmit() {
          // Exit when the form isn't valid
          if (!this.checkFormValidity()) {
            // return 
            console.log(this.info)
          }
          // Hide the modal manually
          this.$nextTick(() => {
            this.$bvModal.hide('modal-prevent-closing')
          })
        }
      },
      created() {
        this.getStaffs();
      },
      mounted() {
        console.log('Component mounted.')
      }
    });
    <link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
    <script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
    
    <div id="app">
      <div class="card-tools">
    
        <b-button class="btn btn-success" v-b-modal.modal-prevent-closing>Add Staff<i class="fas 
                       fa-user-plus fa-fw"></i></b-button>
    
    
    
        <b-modal id="modal-prevent-closing" ref="modal" title="Enter Staff Info" @show="resetModal" @hidden="resetModal" @ok="handleOk">
          <form ref="form" @submit.stop.prevent="handleSubmit">
            <b-form-group label="Name" label-for="name-input" invalid-feedback="Name is required" :state="nameState">
              <b-form-input id="name-input" v-model="info.name" :state="nameState" required></b-form-input>
            </b-form-group>
            <b-form-group label="Email" label-for="email-input" invalid-feedback="Email is required" :state="emailState">
              <b-form-input id="email-input" v-model="info.email" :state="emailState" required></b-form-input>
            </b-form-group>
            <b-form-group label="Phone" label-for="phone-input" invalid-feedback="Phone is required" :state="phoneState">
              <b-form-input id="phone-input" v-model="info.phone" :state="phoneState" required></b-form-input>
            </b-form-group>
            <b-form-group label="Job Title" label-for="job_title-input" invalid-feedback="Job title is required" :state="phoneState">
              <b-form-input id="phone-input" v-model="info.job_title" :state="job_titleState" required></b-form-input>
            </b-form-group>
    
          </form>
        </b-modal>
      </div>
    </div>