Bootstrap Modal Hide from VUE method

12,419

Solution 1

If you are using boostrap, you need to call the hide an show methods from it, because modal api create html elements on the fly (as the dark background)

I recommend to create a save method instead of call the $emit, where you can call the modal hide method before emit the save signal.

<script>
import $ from 'jquery'

export default {
  name: "CreateTodo",
  props: ["mode", "title", "todo"],
  ref: "createTodoModal",
  mounted() {
    if (this.mode == "create") {
      this.title = "Create Todo";
    }
  },
  methods: {
    save() {
       $('#ModalId').modal('hide')
       this.$emit('save')
    }
  }
};
</script>

showModal is not needed in this case.

Solution 2

Add an id to the close X button"

<button type="button" class="close" data-dismiss="modal" aria-label="Close" id="close">
   <span aria-hidden="true">&times;</span>
</button>

Then create a method to close the modal:

closeModal() {
   document.getElementById('close').click();
},

Solution 3

Like @Dan Stoian reply, you can use ref in vue.js :

<button ref="Close" type="button" data-dismiss="modal" ...>
   ...
</button>

And in your handler

this.$refs.Close.click();

Solution 4

You might use v-if to show/hide modal

In your component:

  <div v-if="showModal">
    <div id="todoModal" class="modal fade" role="dialog">
    ...
    </div>
  </div>

and set showModal to true/false to show/hide component respectively.

Solution 5

you can use this npm package

npm i vue-js-modal

https://www.npmjs.com/package/vue-js-modal

Your code should then be modified in this way:

<template>
<modal :name="'edit-modal'+id" height="auto">
    <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Edit {{ mName }}</h5>
        <button type="button" class="close" @click="hideEditModal(id)">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <form action="/user/update" method="patch" @submit.prevent="updateAssistant">
        <div class="modal-body">
            <div class="position-relative form-group">
                <label for="exampleAddress" class="">Full name</label><input name="name" v-model="editName" id="exampleAddress" placeholder="FullName" type="text" class="form-control">
                <div v-if="errors.has('editName')" class="alert alert-danger">
                    {{ errors.first('editName') }}
                </div>
            </div>

            <div class="position-relative form-group">
                <label for="exampleEmail11" class="">Email</label><input name="email" v-model="editEmail" id="exampleEmail11" placeholder="email" type="email" class="form-control">
                <div v-if="errors.has('editEmail')" class="alert alert-danger">
                    {{ errors.first('editEmail') }}
                </div>
            </div>

            <div class="position-relative form-group">
                <label for="examplePassword11" class="">Change Password</label><input name="password" v-model="editPassword" id="examplePassword11" placeholder="password" type="password" class="form-control">
                <div v-if="errors.has('password')" class="alert alert-danger">
                    {{ errors.first('password') }}
                </div>
            </div>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-secondary" @click="hideEditModal(id)">Close</button>
            <button type="submit" class="btn btn-primary">Save changes</button>
        </div>
        <span class="loader" v-if="this.loading" style="position: absolute; bottom: 0.515rem; left: 20px;">
            <span class="ball-clip-rotate">
                <div style=" border:1px solid #000;"></div>
            </span>
        </span>
    </form>
</modal>

import Errors from '../../Errors.js'
export default {

name: 'AssistantEditModalComponent',

props: [
    'mEmail',
    'mName',
    'id'
],

data () {
    return {
        editPassword: null,
        disabled: false,
        errors: Errors,
        loading: false
    }
},

methods: {
    hideEditModal(id) {
        this.$modal.hide('edit-modal'+id);
    },

    setData() {
        this.editName = this.mName
        this.editEmail = this.mEmail
    },

    updateAssistant() {
        this.disabled = true;
        this.loading = true;
        const form = {
            editName: this.mName,
            editEmail: this.mEmail,
            password: this.editPassword
        }
        axios.patch('/user/update/'+this.id, form)
        .then((response) => {
            this.disabled = false
            this.loading = false
            this.hideEditModal(this.id)
            this.alert(response)
        })
        .catch((err) => {
            this.disabled = false
            this.loading = false
            Errors.fill(err.response.data.errors)
        })
    },

    alert(response) {
        swal(response.data.username, response.data.message, 'success')
    },
},

computed: {
    editName: {
        get: function() {
            return this.mName
        },
        set: function(value) {
            this.$emit('update:mName', value);
        }
    },
    editEmail: {
        get: function() {
            return this.mEmail
        },
        set: function(value) {
            this.$emit('update:mEmail', value);
        }
    }
}}
Share:
12,419
Carlos Sosa
Author by

Carlos Sosa

Updated on June 16, 2022

Comments

  • Carlos Sosa
    Carlos Sosa almost 2 years

    I have a vuejs component that displays a modal dialog with a small form inside. When the form is submitted I would like to hide the Modal but cannot figure out how to do it. When submitted the form calls a method in the parent.

    Here is the component code

    <template>
      <div>
        <div id="todoModal" class="modal fade" role="dialog">
          <div class="modal-dialog">
            <div class="modal-content">
              <div class="modal-header">
                <h4 class="modal-title">{{ title }}</h4>
                <button type="button" class="close" data-dismiss="modal">
                  &times;
                </button>
              </div>
              <div class="modal-body">
                <form id="todoForm" @submit.prevent="$emit('save')">
                  <div class="form-group">
                    <label for="name">Todo name</label>
                    <input
                      id="name"
                      v-model="todo.name"
                      type="text"
                      class="form-control"
                      aria-describedby="nameHelp"
                      placeholder="Enter Todo Name"
                    />
                    <small id="nameHelp" class="form-text text-muted"
                      >Enter your todo's name</small
                    >
                  </div>
                </form>
              </div>
              <div class="modal-footer">
                <button class="btn btn-primary mr-4" type="submit" form="todoForm">
                  <span v-if="mode == 'create'">Create</span>
                  <span v-if="mode == 'update'">Update</span>
                </button>
                <button
                  type="button"
                  class="btn btn-danger mr-auto"
                  data-dismiss="modal"
                  @click="
                    $parent.showModal = false;
                    $parent.getTodos();
                  "
                >
                  Cancel
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: "CreateTodo",
      props: ["mode", "title", "todo", "showModal"],
      ref: "createTodoModal",
      mounted() {
        if (this.mode == "create") {
          this.title = "Create Todo";
        }
      },
      methods: {}
    };
    </script>
    <style scoped></style>
    

    And here is my APP.js file

    <template>
      <div id="app" class="container mt-5">
        <router-view
          ref="createtodo"
          class="CreateTodo"
          name="a"
          :todo="todo"
          :title="title"
          :mode="mode"
          :show-modal="showModal"
          @save="saveTodo"
        ></router-view>
      </div>
    </template>
    
    <script>
    import { APIService } from "./APIServices";
    const apiService = new APIService();
    
    export default {
      name: "App",
      data: function() {
        return {
          mode: "create",
          title: "Create Todo",
          todo: {},
          todos: [],
          numberOfTodos: 0,
          showModal: false
        };
      },
      mounted: function() {
        this.getTodos();
      },
    
      methods: {
        saveTodo: function() {
          if (this.mode == "create") {
            apiService.createTodo(this.todo).then(
              result => {
                if (result.status === 200) {
                  this.todo = result.data;
                  this.getTodos();
                }
              },
              error => {}
            );
            this.showModal = false;
            // this.$refs.createtodo.$refs.todoModal
          } else if (this.mode == "update") {
            apiService.updateTodo(this.todo).then(
              result => {
                this.getTodos();
              },
              error => {}
            );
            this.showModal = false;
          } else if (this.mode == "update") {
            apiService.updateTodo(this.todo).then(
              result => {
                this.showModal = false;
                this.getTodos();
              },
              error => {}
            );
          }
        },
      }
    };
    </script>
    
    <style lang="scss">
    </style>
    

    I tried using the ref to reference the Modal from APP.js but it does not work.

    • David SK
      David SK about 5 years
      Review your property "showModal" It is not used to show/hide something. without bootstrap v-show directive could help.
    • Carlos Sosa
      Carlos Sosa about 5 years
      It works, but the modal's dark background does not go away when the modal hides.
  • Carlos Sosa
    Carlos Sosa about 5 years
    Hi Ittus.. Thanks for the suggestion. I tried it and it does work, however when the modal hides the modal's background does not go away,
  • David SK
    David SK about 5 years
    If you are using Bootstrap, you need to hide/show with boostrap methods.
  • ittus
    ittus about 5 years