mirror of
https://github.com/KevinMidboe/vue-js-modal.git
synced 2025-10-29 18:00:20 +00:00
#173 Implement dynamic modals functionality
This commit is contained in:
44
README.md
44
README.md
@@ -133,6 +133,50 @@ this.$modal.show('dialog', {
|
|||||||
<img src="https://user-images.githubusercontent.com/1577802/29165216-ec62552c-7db9-11e7-807e-ef341edcc94d.png">
|
<img src="https://user-images.githubusercontent.com/1577802/29165216-ec62552c-7db9-11e7-807e-ef341edcc94d.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
### Dynamic Modals
|
||||||
|
|
||||||
|
In order to instantiate modals at runtime (for lazy-loading or decluttering templates), it is possible to create modals dynamically.
|
||||||
|
|
||||||
|
To start using this feature you must set `dynamic: true` in plugin configuration:
|
||||||
|
|
||||||
|
```js
|
||||||
|
Vue.use(VModal, { dynamic: true })
|
||||||
|
```
|
||||||
|
|
||||||
|
And include the `<modals-container/>` component it in your project:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<modals-container/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Call it (the first argument is the component definition, the second are component properties, and the third modal parameters):
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
this.$modal.show({
|
||||||
|
template: `
|
||||||
|
<div>
|
||||||
|
<h1>This is created inline</h1>
|
||||||
|
<p>{{ text }}</p>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
props: ['text']
|
||||||
|
}, {
|
||||||
|
text: 'This text is passed as a property'
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
It can also be used with `.vue` files:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import MyComponent from './MyComponent.vue'
|
||||||
|
|
||||||
|
this.$modal.show(MyComponent, {
|
||||||
|
text: 'This text is passed as a property'
|
||||||
|
}, {
|
||||||
|
draggable: true
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
For more examples please take a look at [vue-js-modal.yev.io](http://vue-js-modal.yev.io).
|
For more examples please take a look at [vue-js-modal.yev.io](http://vue-js-modal.yev.io).
|
||||||
|
|
||||||
### SSR
|
### SSR
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
<demo-focus-modal/>
|
<demo-focus-modal/>
|
||||||
<demo-size-modal/>
|
<demo-size-modal/>
|
||||||
|
|
||||||
|
<modals-container />
|
||||||
|
|
||||||
<v-dialog
|
<v-dialog
|
||||||
@before-opened="dialogEvent('before-open')"
|
@before-opened="dialogEvent('before-open')"
|
||||||
@before-closed="dialogEvent('before-close')"
|
@before-closed="dialogEvent('before-close')"
|
||||||
@@ -106,6 +108,22 @@
|
|||||||
@click="showButtonsDialog">
|
@click="showButtonsDialog">
|
||||||
Dialog: buttons
|
Dialog: buttons
|
||||||
</button>
|
</button>
|
||||||
|
<br>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="showDynamicRuntimeModal">
|
||||||
|
Dynamic: Runtime Modal
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="showDynamicComponentModal">
|
||||||
|
Dynamic: Component Modal
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn"
|
||||||
|
@click="showDynamicComponentModalWithModalParams">
|
||||||
|
Dynamic: Component Modal with modal params
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -118,6 +136,7 @@ import DemoLoginModal from './components/DemoLoginModal.vue'
|
|||||||
import DemoDogProfileModal from './components/DogProfileModal.vue'
|
import DemoDogProfileModal from './components/DogProfileModal.vue'
|
||||||
import DemoConditionalModal from './components/ConditionalModal.vue'
|
import DemoConditionalModal from './components/ConditionalModal.vue'
|
||||||
import DemoSizeModal from './components/SizeModal.vue'
|
import DemoSizeModal from './components/SizeModal.vue'
|
||||||
|
import CustomComponentModal from './components/CustomComponentModal.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
@@ -203,6 +222,36 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showDynamicRuntimeModal () {
|
||||||
|
this.$modal.show({
|
||||||
|
template: `
|
||||||
|
<div>
|
||||||
|
<h1>This is created inline</h1>
|
||||||
|
<p>{{ text }}</p>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
props: ['text']
|
||||||
|
}, {
|
||||||
|
text: 'This text is passed as a property'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
showDynamicComponentModal () {
|
||||||
|
this.$modal.show(CustomComponentModal, {
|
||||||
|
text: 'This text is passed as a property'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
showDynamicComponentModalWithModalParams () {
|
||||||
|
this.$modal.show(CustomComponentModal, {
|
||||||
|
text: 'This text is passed as a property'
|
||||||
|
}, {
|
||||||
|
resizable: true,
|
||||||
|
adaptive: true,
|
||||||
|
draggable: true,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
dialogEvent (eventName) {
|
dialogEvent (eventName) {
|
||||||
console.log('Dialog event: ' + eventName)
|
console.log('Dialog event: ' + eventName)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>This is a custom component</h1>
|
||||||
|
<p>{{ text }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: ['text']
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -3,7 +3,8 @@ import App from './App.vue'
|
|||||||
import VueJsModal from 'plugin'
|
import VueJsModal from 'plugin'
|
||||||
|
|
||||||
Vue.use(VueJsModal, {
|
Vue.use(VueJsModal, {
|
||||||
dialog: true
|
dialog: true,
|
||||||
|
dynamic: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"build:ssr-no-css": "webpack --config ./build/webpack.ssr-no-css.config.js --progress --hide-modules",
|
"build:ssr-no-css": "webpack --config ./build/webpack.ssr-no-css.config.js --progress --hide-modules",
|
||||||
"lint": "eslint --ext .js,.vue src test/unit/specs",
|
"lint": "eslint --ext .js,.vue src test/unit/specs",
|
||||||
"unit": "./node_modules/karma/bin/karma start test/unit/karma.conf.js",
|
"unit": "./node_modules/karma/bin/karma start test/unit/karma.conf.js",
|
||||||
|
"watch": "webpack --config ./build/webpack.client.config.js --progress --hide-modules --watch",
|
||||||
"build": "npm run build:client && npm run build:ssr && npm run build:ssr-no-css",
|
"build": "npm run build:client && npm run build:ssr && npm run build:ssr-no-css",
|
||||||
"test:types": "tsc -p types/test"
|
"test:types": "tsc -p types/test"
|
||||||
},
|
},
|
||||||
|
|||||||
50
src/ModalsContainer.vue
Normal file
50
src/ModalsContainer.vue
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<div id="#modals-container">
|
||||||
|
<modal
|
||||||
|
v-for="modal in modals"
|
||||||
|
:key="modal.id"
|
||||||
|
:name="modal.name"
|
||||||
|
v-bind="modal.config"
|
||||||
|
@closed="remove(modal.id)"
|
||||||
|
>
|
||||||
|
<component :is="modal.component" v-bind="modal.params"></component>
|
||||||
|
</modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
uid: 0,
|
||||||
|
modals: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.$modal._setDynamicContainer(this)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
add (modal, params, config) {
|
||||||
|
let id = this.uid++
|
||||||
|
let name = '_dynamic-modal-' + id
|
||||||
|
this.modals.push({
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
component: modal,
|
||||||
|
params: params || {},
|
||||||
|
config: config || {}
|
||||||
|
})
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$modal.show(name)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
remove (id) {
|
||||||
|
for (let i in this.modals) {
|
||||||
|
if (this.modals[i].id === id) {
|
||||||
|
this.modals.splice(i, 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
25
src/index.js
25
src/index.js
@@ -1,5 +1,6 @@
|
|||||||
import Modal from './Modal.vue'
|
import Modal from './Modal.vue'
|
||||||
import Dialog from './Dialog.vue'
|
import Dialog from './Dialog.vue'
|
||||||
|
import ModalsContainer from './ModalsContainer.vue'
|
||||||
|
|
||||||
const defaultComponentName = 'modal'
|
const defaultComponentName = 'modal'
|
||||||
|
|
||||||
@@ -14,14 +15,26 @@ const Plugin = {
|
|||||||
|
|
||||||
this.installed = true
|
this.installed = true
|
||||||
this.event = new Vue()
|
this.event = new Vue()
|
||||||
|
this.dynamicContainer = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin API
|
* Plugin API
|
||||||
*/
|
*/
|
||||||
Vue.prototype.$modal = {
|
Vue.prototype.$modal = {
|
||||||
show (name, params) {
|
_setDynamicContainer (dynamicContainer) {
|
||||||
Plugin.event.$emit('toggle', name, true, params)
|
Plugin.dynamicContainer = dynamicContainer
|
||||||
|
},
|
||||||
|
show (modal, paramsOrProps, params) {
|
||||||
|
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')
|
||||||
|
} else {
|
||||||
|
Plugin.dynamicContainer.add(modal, paramsOrProps, params)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hide (name, params) {
|
hide (name, params) {
|
||||||
Plugin.event.$emit('toggle', name, false, params)
|
Plugin.event.$emit('toggle', name, false, params)
|
||||||
},
|
},
|
||||||
@@ -41,6 +54,12 @@ const Plugin = {
|
|||||||
if (options.dialog) {
|
if (options.dialog) {
|
||||||
Vue.component('v-dialog', Dialog)
|
Vue.component('v-dialog', Dialog)
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Registration of <ModalsContainer/> component
|
||||||
|
*/
|
||||||
|
if (options.dynamic) {
|
||||||
|
Vue.component('modals-container', ModalsContainer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
types/index.d.ts
vendored
4
types/index.d.ts
vendored
@@ -1,4 +1,4 @@
|
|||||||
import Vue, { PluginObject } from "vue";
|
import Vue, { PluginObject, ComponentOptions } from "vue";
|
||||||
|
|
||||||
declare const VueJSModal: PluginObject<VueJSModalOptions>;
|
declare const VueJSModal: PluginObject<VueJSModalOptions>;
|
||||||
export default VueJSModal;
|
export default VueJSModal;
|
||||||
@@ -9,7 +9,7 @@ export declare interface VueJSModalOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare interface VModal {
|
declare interface VModal {
|
||||||
show(name: string, params?: object): void;
|
show(modal: string | typeof Vue | ComponentOptions<Vue>, paramsOrProps?: object, params?: object): void;
|
||||||
hide(name: string, params?: object): void;
|
hide(name: string, params?: object): void;
|
||||||
toggle(name: string, params?: object): void;
|
toggle(name: string, params?: object): void;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user