DaFunkyAlex
DaFunkyAlex

Reputation: 1969

Vue.js 2: Modal Dialog - close when Method is successful

I have the following directive:

import Vue from 'vue'

const Dialog = Vue.extend({
    template: `
    <div v-if="show" class="modal">
        <div class="modal-body">
            <div class="modal-header"><h3>Aktion bestätigen</h3></div>
            <div class="modal-content">
                <div class="uk-flex">
                    <div class="uk-margin-small-right">
                        <span uk-icon="icon: question; ratio: 3"></span>
                    </div>
                    <div>
                        Are You sure?
                    </div>
                </div>
                <hr>
                <div class="uk-flex uk-flex-right">
                    <button class="uk-button uk-button-danger uk-margin-small-right" @click="confirmed">Yes</button>
                    <button class="uk-button uk-button-default" @click="show = false">Cancel</button>
                </div>
            </div>
        </div>
    </div>
  `
});

Vue.directive('confirm', {
    bind(el, binding, vnode) {
        let confirm_method = binding.value;
        el.handleClick = (e) => {
            const data = { confirmed: confirm_method , show: true};
            let dialog = new Dialog({data: data}).$mount();
            document.getElementsByTagName('body')[0].appendChild(dialog.$el);
        }
        el.addEventListener('click', el.handleClick);
    },
    unbind(el) {
        el.removeEventListener('click', el.handleClick);
    }
});

This works fine. When I click on "Cancel", the modal closes. When I click "Yes", the method defined in Vue template

<button v-confirm="delete">delete</button>

is executed.

But the modal does not appear. How to tell the modal to close after the method has been executed, and maybe show an error message, when there was an error?

Upvotes: 0

Views: 5186

Answers (2)

h1784487
h1784487

Reputation: 31

Vue documentation has pretty good example of modal.
The key option is $emit('close'). You can call $emit('close') on your method success.

// register modal component
Vue.component('modal', {
  template: '#modal-template'
})

// start app
new Vue({
  el: '#app',
  data: {
    showModal: false
  }
})
.modal-mask {
  position: fixed;
  z-index: 9998;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, .5);
  display: table;
  transition: opacity .3s ease;
}

.modal-wrapper {
  display: table-cell;
  vertical-align: middle;
}

.modal-container {
  width: 300px;
  margin: 0px auto;
  padding: 20px 30px;
  background-color: #fff;
  border-radius: 2px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
  transition: all .3s ease;
  font-family: Helvetica, Arial, sans-serif;
}

.modal-header h3 {
  margin-top: 0;
  color: #42b983;
}

.modal-body {
  margin: 20px 0;
}

.modal-default-button {
  float: right;
}

/*
 * The following styles are auto-applied to elements with
 * transition="modal" when their visibility is toggled
 * by Vue.js.
 *
 * You can easily play with the modal transition by editing
 * these styles.
 */

.modal-enter {
  opacity: 0;
}

.modal-leave-active {
  opacity: 0;
}

.modal-enter .modal-container,
.modal-leave-active .modal-container {
  -webkit-transform: scale(1.1);
  transform: scale(1.1);
}
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<!-- template for the modal component -->
<script type="text/x-template" id="modal-template">
  <transition name="modal">
    <div class="modal-mask">
      <div class="modal-wrapper">
        <div class="modal-container">

          <div class="modal-header">
            <slot name="header">
              default header
            </slot>
          </div>

          <div class="modal-body">
            <slot name="body">
              default body
            </slot>
          </div>

          <div class="modal-footer">
            <slot name="footer">
              default footer
              <button class="modal-default-button" @click="$emit('close')">
                OK
              </button>
            </slot>
          </div>
        </div>
      </div>
    </div>
  </transition>
</script>

<!-- app -->
<div id="app">
  <button id="show-modal" @click="showModal = true">Show Modal</button>
  <!-- use the modal component, pass in the prop -->
  <modal v-if="showModal" @close="showModal = false">
    <!--
      you can use custom content here to overwrite
      default content
    -->
    <h3 slot="header">custom header</h3>
  </modal>
</div>

Upvotes: 1

ittus
ittus

Reputation: 22393

You can pass methods to Dialog:

Vue.directive('confirm', {
    bind(el, binding, vnode) {
         let confirm_method = binding.value;
         el.handleClick = (e) => {
             const data = { confirmed: confirm_method , show: true};
             let dialog = new Dialog({
                        data: data, 
                  methods: {
                    confirmedInternal() {
                      this.show = false
                      this.confirmed()
                    }
                  }
             }).$mount();
             document.getElementsByTagName('body')[0].appendChild(dialog.$el);
         }
         el.addEventListener('click', el.handleClick);
    },
    unbind(el) {
        el.removeEventListener('click', el.handleClick);
    }
});

then calling confirmedInternal when yes button is click

 <button class="uk-button uk-button-danger uk-margin-small-right" @click="confirmedInternal">Yes</button>

Demo: https://jsfiddle.net/guqc2src/

Upvotes: 1

Related Questions