From 19c8d3a05c8b3e6e72c159d1f15c43d272a25752 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Sun, 19 Aug 2018 20:48:45 +0200 Subject: [PATCH 1/3] Use Vue root instance when injecting modals container --- README.md | 20 ++++++++++++++++++++ src/ModalsContainer.vue | 2 +- src/index.js | 38 ++++++++++++++++++++++++-------------- types/index.d.ts | 4 +++- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 176a30fe..c618ae10 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,25 @@ this.$modal.show({ }) ``` +If using the `injectModalsContainer` flag, the first mounted Vue instance without parents will be treated as the application root. This is only important to keep in mind if more than one root Vue instance is being used, which is unlikely. But if that's the case, the root to use can be indicated with the `root` parameter when invoking dynamic modals or modifying this plugin's `rootInstance` attribute: + +```javascript +import App from './App.vue' +import VModal from 'vue-js-modal' + +const app1 = new Vue({ + el: '#app-1', + render: h => h(App) +}) + +const app2 = new Vue({ + el: '#app-2', + render: h => h(App) +}) + +VModal.rootInstance = app2 +``` + For more examples please take a look at [vue-js-modal.yev.io](http://vue-js-modal.yev.io). **Note:** keep in mind that there are some limitations for using dynamic modals. If you need full functionality then use ordinary modal instead. @@ -257,6 +276,7 @@ There is also a ssr build with css file extracted. Take a look in /dist folder. | maxHeight | false | Number (px) | Infinity | The maximum height of the modal (if the value is greater than window height, window height will be used instead | | pivotX | false | Number (0 - 1.0) | 0.5 | Horizontal position in %, default is 0.5 (meaning that modal box will be in the middle (50% from left) of the window | | pivotY | false | Number (0 - 1.0) | 0.5 | Vertical position in %, default is 0.5 (meaning that modal box will be in the middle (50% from top) of the window | +| root | false | Vue instance | null | Root instance to obtain modal container from. This property is only necessary when using dynamic modals with more than one root instance, which is uncommon | ### Events diff --git a/src/ModalsContainer.vue b/src/ModalsContainer.vue index 48481718..a4621784 100644 --- a/src/ModalsContainer.vue +++ b/src/ModalsContainer.vue @@ -25,7 +25,7 @@ export default { } }, created () { - this.$modal._setDynamicContainer(this) + this.$root._dynamicContainer = this }, methods: { add (modal, params, config, events) { diff --git a/src/index.js b/src/index.js index ca260cab..8e70dd57 100644 --- a/src/index.js +++ b/src/index.js @@ -15,23 +15,32 @@ const Plugin = { this.installed = true this.event = new Vue() - this.dynamicContainer = null + this.rootInstance = null this.componentName = options.componentName || defaultComponentName /** * Plugin API */ Vue.prototype.$modal = { - _setDynamicContainer (dynamicContainer) { - Plugin.dynamicContainer = dynamicContainer - }, show (modal, paramsOrProps, params, events = {}) { if (typeof modal === 'string') { Plugin.event.$emit('toggle', modal, true, paramsOrProps) } else { - if (Plugin.dynamicContainer === null) { - console.warn('[vue-js-modal] In order to render dynamic modals, a component must be present on the page') + let root = Plugin.rootInstance + if (params && params.root) { + root = params.root + } + if (options.injectModalsContainer && !root._dynamicContainer) { + const modalsContainer = document.createElement('div') + document.body.appendChild(modalsContainer) + new Vue({ + parent: root, + render: h => h(ModalsContainer) + }).$mount(modalsContainer) + } + if (root._dynamicContainer) { + root._dynamicContainer.add(modal, paramsOrProps, params, events) } else { - Plugin.dynamicContainer.add(modal, paramsOrProps, params, events) + console.warn('[vue-js-modal] In order to render dynamic modals, a component must be present on the page') } } }, @@ -57,13 +66,14 @@ const Plugin = { * Registration of component */ if (options.dynamic) { - if (options.injectModalsContainer) { - const modalsContainer = document.createElement('div') - document.body.appendChild(modalsContainer) - new Vue({ render: h => h(ModalsContainer) }).$mount(modalsContainer) - } else { - Vue.component('modals-container', ModalsContainer) - } + Vue.component('modals-container', ModalsContainer) + Vue.mixin({ + beforeMount () { + if (Plugin.rootInstance === null) { + Plugin.rootInstance = this.$root + } + } + }) } } } diff --git a/types/index.d.ts b/types/index.d.ts index 19c55ab2..7d323fa9 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,6 +1,8 @@ import Vue, { PluginObject, ComponentOptions } from "vue"; -declare const VueJSModal: PluginObject; +declare const VueJSModal: PluginObject & { + rootInstance?: Vue +}; export default VueJSModal; export declare interface VueJSModalOptions { From 77a4562f05d40c4958cb0a8d85279e1a17a92ff8 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Mon, 20 Aug 2018 20:49:56 +0200 Subject: [PATCH 2/3] Extract injectModalsContainer behaviour into a separate function --- src/index.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/index.js b/src/index.js index 8e70dd57..b82576b6 100644 --- a/src/index.js +++ b/src/index.js @@ -30,12 +30,7 @@ const Plugin = { root = params.root } if (options.injectModalsContainer && !root._dynamicContainer) { - const modalsContainer = document.createElement('div') - document.body.appendChild(modalsContainer) - new Vue({ - parent: root, - render: h => h(ModalsContainer) - }).$mount(modalsContainer) + injectModalsContainer(Vue, root) } if (root._dynamicContainer) { root._dynamicContainer.add(modal, paramsOrProps, params, events) @@ -78,4 +73,13 @@ const Plugin = { } } +function injectModalsContainer (Vue, parent) { + const modalsContainer = document.createElement('div') + document.body.appendChild(modalsContainer) + new Vue({ + parent: parent, + render: h => h(ModalsContainer) + }).$mount(modalsContainer) +} + export default Plugin From 085918823046e91247ba4c74943f9a3f13f6bfea Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Mon, 20 Aug 2018 20:58:05 +0200 Subject: [PATCH 3/3] Encapsulate more functionality into function for retrieving modals container instance --- src/index.js | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/index.js b/src/index.js index b82576b6..c7908854 100644 --- a/src/index.js +++ b/src/index.js @@ -29,11 +29,10 @@ const Plugin = { if (params && params.root) { root = params.root } - if (options.injectModalsContainer && !root._dynamicContainer) { - injectModalsContainer(Vue, root) - } - if (root._dynamicContainer) { - root._dynamicContainer.add(modal, paramsOrProps, params, events) + + const dynamicContainer = getModalsContainer(Vue, options, root) + if (dynamicContainer) { + dynamicContainer.add(modal, paramsOrProps, params, events) } else { console.warn('[vue-js-modal] In order to render dynamic modals, a component must be present on the page') } @@ -73,13 +72,17 @@ const Plugin = { } } -function injectModalsContainer (Vue, parent) { - const modalsContainer = document.createElement('div') - document.body.appendChild(modalsContainer) - new Vue({ - parent: parent, - render: h => h(ModalsContainer) - }).$mount(modalsContainer) +function getModalsContainer (Vue, options, root) { + if (!root._dynamicContainer && options.injectModalsContainer) { + const modalsContainer = document.createElement('div') + document.body.appendChild(modalsContainer) + new Vue({ + parent: root, + render: h => h(ModalsContainer) + }).$mount(modalsContainer) + } + + return root._dynamicContainer } export default Plugin