Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion src/ModalsContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default {
}
},
created () {
this.$modal._setDynamicContainer(this)
this.$root._dynamicContainer = this
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This $root, is this the Vue instance? If so, I feel slightly worried that we write smth into it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is. I am using the _ prefix to have Vue ignore them, as explained here: https://vuejs.org/v2/api/#data The only problem I can see with this is if other plugin, or Vue itself, uses the same property name which I don't think it's likely. In that case, we could go even further and namespace the property, something like _vueJSModalDynamicContainer but I don't think it's necessary.

In any case, if you are not comfortable with this we can also store this in our plugin, having an object that maps from root instances to dynamic containers.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation, i actually didnt know about _ and $ prefixed functions 😄

},
methods: {
add (modal, params, config, events) {
Expand Down
45 changes: 31 additions & 14 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,26 @@ 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 <modals-container> component must be present on the page')
let root = Plugin.rootInstance
if (params && params.root) {
root = params.root
Copy link
Owner

@euvl euvl Aug 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not entirely familiar with the code, so might ask stupid questions.

is it intended that param.root overwrites Plugin.rootInstance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't worry, ask whatever you want :D. Yes, it is intended. As I explained in the documentation, in the unlikely case that someone has a Vue application with more than one root, it is possible that they want to open modals for different component trees. In which case, you would indicate which parent to use with this parameter (which would indicate what store to use or any other plugins).

}

const dynamicContainer = getModalsContainer(Vue, options, root)
if (dynamicContainer) {
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 <modals-container> component must be present on the page')
}
}
},
Expand All @@ -57,15 +60,29 @@ const Plugin = {
* Registration of <ModalsContainer/> 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
Copy link
Owner

@euvl euvl Aug 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty cool, I didn't know one can do it this way

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, quite frankly it's kind of "hacky" and I'm not entirely convinced of doing it this way. Because this will be called for every Vue instance, not only the "root". But there is really no way, as far as I know, to have a callback only when "root" instances are created, since a root instance is only a Vue instance without parents, there is nothing more special about them.

}
}
})
}
}
}

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
4 changes: 3 additions & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Vue, { PluginObject, ComponentOptions } from "vue";

declare const VueJSModal: PluginObject<VueJSModalOptions>;
declare const VueJSModal: PluginObject<VueJSModalOptions> & {
rootInstance?: Vue
};
export default VueJSModal;

export declare interface VueJSModalOptions {
Expand Down