[Vuejs]-How to write a plugin that shows a modal popup using vue. Call should be made as a function()

0👍

Try to avoiding $ref with vue ( $ref is here for third party and some very special case )
$ref isn’t reactive and is populate after the render …

the best solution for me is using a event bus like this :

const EventBus = new Vue({
      name: 'EventBus',
});
Vue.set(Vue.prototype, '$bus', EventBus);

And then use the event bus for calling function of your modal …

(
this.$bus.on('event-name', callback) / this.$bus.off('event-name');
this.$bus.$emit('event-name', payload);
)


You can create a little wrapper around the bootstrap modal like mine
( exept a use the sweet-modal)

<template>
  <div>
    <sweet-modal
      :ref="modalUid"
      :title="title"
      :width="width"
      :class="klass"
      class="modal-form"
      @open="onModalOpen"
      @close="onModalClose"
    >
      <slot />
    </sweet-modal>
  </div>
</template>

<script>
  export default {
    name: 'TModal',
    props: {
      eventId: {
        type: String,
        default: null,
      },
      title: {
        type: String,
        default: null,
      },
      width: {
        type: String,
        default: null,
      },
      klass: {
        type: String,
        default: '',
      },
    },
    computed: {
      modalUid() {
        return `${this._uid}_modal`; // eslint-disable-line no-underscore-dangle
      },
      modalRef() {
        return this.$refs[this.modalUid];
      },
    },
    mounted() {
      if (this.eventId !== null) {
        this.$bus.$on([this.eventName('open'), this.eventName('close')], this.catchModalArguments);
        this.$bus.$on(this.eventName('open'), this.modalRef ? this.modalRef.open : this._.noop);
        this.$bus.$on(this.eventName('close'), this.modalRef ? this.modalRef.close : this._.noop);
      }
    },
    beforeDestroy() {
      if (this.eventId !== null) {
        this.$off([this.eventName('open'), this.eventName('close')]);
      }
    },
    methods: {
      onModalOpen() {
        this.$bus.$emit(this.eventName('opened'), ...this.modalRef.args);
      },
      onModalClose() {
        if (this.modalRef.is_open) {
          this.$bus.$emit(this.eventName('closed'), ...this.modalRef.args);
        }
      },
      eventName(action) {
        return `t-event.t-modal.${this.eventId}.${action}`;
      },
      catchModalArguments(...args) {
        if (this.modalRef) {
          this.modalRef.args = args || [];
        }
      },
    },
  };
</script>

<style lang="scss" scoped>
  /deep/ .sweet-modal {
    .sweet-title > h2 {
      line-height: 64px !important;
      margin: 0 !important;
    }
  }
</style>

0👍

AppModal.vue

<template>
  <div class="modal-wrapper" v-if="visible">
    <h2>{{ title }}</h2>
    <p>{{ text }}</p>
    <div class="modal-buttons">
      <button class="modal-button" @click="hide">Close</button>
      <button class="modal-button" @click="confirm">Confirm</button>
    </div>
  </div>
</template>


<script>
export default {
  data() {
    return {
      visible: false, 
      title: '',
      text: ''
    }
  },
  methods: {
    hide() {
      this.visible = false;
    },
  }
}
</script>

Modal.js (plugin)

import AppModal from 'AppModal.vue'

const Modal = {
  install(Vue, options) {
    this.EventBus = new Vue()
    Vue.component('app-modal', AppModal)
    Vue.prototype.$modal = {
      show(params) {
        Modal.EventBus.$emit('show', params)
      }
    }
  }
}

export default Modal

main.js

import Modal from 'plugin.js'
// ...
Vue.use(Modal)

App.vue

<template>
  <div id="app">
    // ... 
    <app-modal/>
  </div>
</template>

-4👍

This looks pretty complicated. Why don’t you use a ready-to-use popup component like this one? https://www.npmjs.com/package/@soldeplata/popper-vue

Leave a comment