Leonardo
Leonardo

Reputation: 2485

Close a bootstrap modal 5 after asynchronously submitting a form with vue js

I am trying to hide a modal after submitting a form. I am using bootstrap 5, vue 2 and django 3.2. I am a beginner in javascript and vue. I can asynchronously submit the form with fetch and clear the fields, but I can't close the modal.

I report part of my code (bootstrap and vue only) which unfortunately does not provide a minimum reproducible example, but I hope it is sufficient.

The html template is:

<div style="margin-right: 230px" id="app">
        
    <h4 style="text-align:left;float:left;">User Managment</h4>
    <a 
        href="#" 
        data-bs-toggle="modal" 
        data-bs-target="#add_userModal"
        class="btn btn-sm btn-outline-primary px-4" 
        style="text-align:right; float:right;">
            Add
    </a>
    <hr style="clear:both; border-top: 1px solid grey;"/>

    <table class="table" id="userTable">
        <thead>
        <tr>
            <th class="col-md-4">First name</th>
            <th class="col-md-8">Last name</th>
        </tr>
        </thead>
        <tbody>
            <tr v-for="userdb in usersdb">
                <td><a href="#">{% verbatim %}{{ userdb.first_name }}{% endverbatim %}</a></td>
                <td><a href="#">{% verbatim %}{{ userdb.last_name }}{% endverbatim %}</a></td>
            </tr>
        </tbody>
    </table>

    <div class="modal fade" id="add_userModal" tabindex="-1" aria-labelledby="add_userModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="staticBackdropLabel">Utente</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <form @submit.prevent="createUserdb">
            <div class="modal-body">

              <div class="form-group mb-3">
                <label>First name*</label>
                <input
                  type="text"
                  class="form-control"
                  id="first_name"
                  v-model="userdb.first_name"
                  required>
              </div>

              <div class="form-group mb-3">
                <label>Last name*</label>
                <input
                  type="text"
                  class="form-control"
                  id="last_name"
                  v-model="userdb.last_name"
                  required>
              </div>

            </div>
            <div class="modal-footer">
              <button type="button" class="btn btn-sm btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
              <button type="submit" class="btn btn-sm btn-outline-primary">Add</button>
            </div>
          </form>
        </div>
      </div>
    </div>
</div>

The javascript code is

var app = new Vue({
    el: '#app', 
    data: {
        csrf: null,
        userdb: {
            first_name: '', 
            last_name: '', 
            full_name: ''}, 
        usersdb: []
    }, 

    methods: {
        async sendRequest(url, method, data) {
            var myHeaders = new Headers({
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest'
            })

            if (method !== 'get') {
                myHeaders.set('X-CSRFToken', await this.getCsrfToken())
            };

            var response = await fetch(url, {
                method: method, 
                headers: myHeaders, 
                body: data
            });

            return response
        },

        async getCsrfToken() {
            if (this.csrf === null) {
                var response = await this.sendRequest(mainUrl + 'csrf', 'get')
                var data = await response.json();
                this.csrf = data.csrf_token;
            };
            return this.csrf;
        }, 

        async getUserdb() {
            var response = await this.sendRequest(mainUrl, 'get'); 
            this.usersdb = await response.json();
        }, 

        async createUserdb() {
            await this.getUserdb();

            await this.sendRequest(mainUrl, 'post', JSON.stringify(this.userdb));
            
            this.userdb.first_name = '';
            this.userdb.last_name = '';
            await this.getUserdb();
        }
    },

    async created() {
        await this.getUserdb();
    }
})

I made many attempts to add code in createUserdb, but without success. For example

document.getElementById("add_userModal").hide();

How can I hide the modal after submitting the form?

Any help is truly appreciated

Upvotes: 1

Views: 11993

Answers (1)

Carol Skelly
Carol Skelly

Reputation: 362350

You'll want to entirely manage the Bootstrap modal instance in the Vue app...

1 - First, add a new data var for the modal..

data: {
        csrf: null,
        userdb: {
            first_name: '', 
            last_name: '', 
            full_name: ''}, 
        usersdb: [],
        myModal: null
    }, 

2 - And a new method (ie: showModal()) to get an instance of the Bootstrap.modal and show it...

    showModal(){
        this.myModal = new bootstrap.Modal(document.getElementById('add_userModal'), {})
        this.myModal.show()
    },

3 - Bind the new method to @click handler to show the modal (instead of using data-bs attributes)...

   <a 
        @click="showModal()"
        class="btn btn-sm btn-outline-primary px-4" 
        style="text-align:right; float:right;">
            Add
   </a>

4 - Finally, call the hide() method after the async processing...

    async createUserdb() {
          await this.getUserdb();
          await this.sendRequest(mainUrl, 'post', JSON.stringify(this.userdb));
          this.userdb.first_name = '';
          this.userdb.last_name = '';
          this.myModal.hide()
    }

Demo

Upvotes: 6

Related Questions