From c36dfb3c3961edbe9c2d6d8b05b0d6915d086e5c Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Thu, 15 Feb 2018 18:29:42 +0100 Subject: [PATCH] #173 Implement dynamic modals functionality --- README.md | 48 +++++++++++++++++- demo/client_side_rendering/src/App.vue | 49 ++++++++++++++++++ .../src/components/CustomComponentModal.vue | 12 +++++ demo/client_side_rendering/src/main.js | 3 +- package.json | 1 + src/ModalsContainer.vue | 50 +++++++++++++++++++ src/index.js | 25 ++++++++-- types/index.d.ts | 4 +- 8 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 demo/client_side_rendering/src/components/CustomComponentModal.vue create mode 100644 src/ModalsContainer.vue diff --git a/README.md b/README.md index cda03f3..c767b0d 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ this.$modal.show('dialog', { title: 'Alert!', text: 'You are too awesome', buttons: [ - { + { title: 'Deal with it', handler: () => { alert('Woot!') } }, @@ -122,7 +122,7 @@ this.$modal.show('dialog', { default: true, // Will be triggered by default if 'Enter' pressed. handler: () => {} // Button click handler }, - { + { title: 'Close' } ] @@ -133,6 +133,50 @@ this.$modal.show('dialog', {

+### 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 `` component it in your project: + +```vue + +``` + +Call it (the first argument is the component definition, the second are component properties, and the third modal parameters): + +```javascript +this.$modal.show({ + template: ` +
+

This is created inline

+

{{ text }}

+
+ `, + 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). ### SSR diff --git a/demo/client_side_rendering/src/App.vue b/demo/client_side_rendering/src/App.vue index 5772188..b49fcc5 100644 --- a/demo/client_side_rendering/src/App.vue +++ b/demo/client_side_rendering/src/App.vue @@ -7,6 +7,8 @@ + + Dialog: buttons +
+ + + @@ -118,6 +136,7 @@ import DemoLoginModal from './components/DemoLoginModal.vue' import DemoDogProfileModal from './components/DogProfileModal.vue' import DemoConditionalModal from './components/ConditionalModal.vue' import DemoSizeModal from './components/SizeModal.vue' +import CustomComponentModal from './components/CustomComponentModal.vue' export default { name: 'app', @@ -203,6 +222,36 @@ export default { }) }, + showDynamicRuntimeModal () { + this.$modal.show({ + template: ` +
+

This is created inline

+

{{ text }}

+
+ `, + 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) { console.log('Dialog event: ' + eventName) } diff --git a/demo/client_side_rendering/src/components/CustomComponentModal.vue b/demo/client_side_rendering/src/components/CustomComponentModal.vue new file mode 100644 index 0000000..ac4b322 --- /dev/null +++ b/demo/client_side_rendering/src/components/CustomComponentModal.vue @@ -0,0 +1,12 @@ + + + diff --git a/demo/client_side_rendering/src/main.js b/demo/client_side_rendering/src/main.js index e88b15c..2a5aab7 100644 --- a/demo/client_side_rendering/src/main.js +++ b/demo/client_side_rendering/src/main.js @@ -3,7 +3,8 @@ import App from './App.vue' import VueJsModal from 'plugin' Vue.use(VueJsModal, { - dialog: true + dialog: true, + dynamic: true, }) new Vue({ diff --git a/package.json b/package.json index 65ae70a..3fffe85 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "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", "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", "test:types": "tsc -p types/test" }, diff --git a/src/ModalsContainer.vue b/src/ModalsContainer.vue new file mode 100644 index 0000000..479dedd --- /dev/null +++ b/src/ModalsContainer.vue @@ -0,0 +1,50 @@ + + diff --git a/src/index.js b/src/index.js index 1ed9163..ef0a566 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ import Modal from './Modal.vue' import Dialog from './Dialog.vue' +import ModalsContainer from './ModalsContainer.vue' const defaultComponentName = 'modal' @@ -14,14 +15,26 @@ const Plugin = { this.installed = true this.event = new Vue() + this.dynamicContainer = null + /** * Plugin API */ Vue.prototype.$modal = { - show (name, params) { - Plugin.event.$emit('toggle', name, true, params) + _setDynamicContainer (dynamicContainer) { + 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 component must be present on the page') + } else { + Plugin.dynamicContainer.add(modal, paramsOrProps, params) + } + } }, - hide (name, params) { Plugin.event.$emit('toggle', name, false, params) }, @@ -41,6 +54,12 @@ const Plugin = { if (options.dialog) { Vue.component('v-dialog', Dialog) } + /** + * Registration of component + */ + if (options.dynamic) { + Vue.component('modals-container', ModalsContainer) + } } } diff --git a/types/index.d.ts b/types/index.d.ts index a2a7d12..0ca8d46 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,4 +1,4 @@ -import Vue, { PluginObject } from "vue"; +import Vue, { PluginObject, ComponentOptions } from "vue"; declare const VueJSModal: PluginObject; export default VueJSModal; @@ -9,7 +9,7 @@ export declare interface VueJSModalOptions { } declare interface VModal { - show(name: string, params?: object): void; + show(modal: string | typeof Vue | ComponentOptions, paramsOrProps?: object, params?: object): void; hide(name: string, params?: object): void; toggle(name: string, params?: object): void; }