Skip to content

Commit 5ddb1d4

Browse files
Merge pull request #6 from ThomasLeconte/develop
Feat: Add of custom component on dialog
2 parents 0448c8d + fd21c9c commit 5ddb1d4

File tree

8 files changed

+124
-7
lines changed

8 files changed

+124
-7
lines changed

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,34 @@ this.$dialog.create({
4848
],
4949
cardOptions: {
5050
//any v-card api options
51+
},
52+
dialogOptions: {
53+
//any v-dialog api options
5154
}
5255
}).then((anwser) => {
5356
//Do something with the anwser corresponding to the key of the clicked button
5457
})
5558
```
59+
<br>
60+
<hr>
61+
62+
#### **NEW (V1.3.3)**
63+
You can pass a custom component to render inside the dialog, with it props binded! Here's how to do it :
64+
```js
65+
this.$dialog.create({
66+
..., //other options
67+
customComponent: {
68+
component: MyCustomComponent,
69+
props: { myComponentProp: 'Hello world!' }
70+
},
71+
}).then(() => {
72+
})
73+
```
74+
> [!WARNING]
75+
> ⚠ If you declare a persistent dialog option, take care that your component emit a `closeDialog` event when you want to close it.
76+
77+
<hr>
78+
<br>
5679

5780
`this.$dialog` also have a `confirm` method, which is a shortcut for the previous method with only two buttons : "Yes" and "No".
5881
```js

cypress/test-server/src/components/HelloWorld.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<h3 class="primary-text">Dialogs</h3>
1616
<div class="mt-5">
1717
<v-btn id="create-dialog" @click="createDialog()">Create Dialog</v-btn>
18+
<v-btn id="create-custom-component-dialog" @click="createCustomComponentDialog()" color="warning">Custom component Dialog</v-btn>
1819
<v-btn id="success-dialog" @click="successDialog()" color="success">Success Dialog</v-btn>
1920
<v-btn id="confirm-dialog" @click="confirmDialog()" color="primary">Confirm Dialog</v-btn>
2021
</div>
@@ -57,12 +58,14 @@
5758
<script lang="ts">
5859
import { defineComponent } from "vue";
5960
import sfcExampleVue from "./sfc-example.vue";
61+
import MyComponent from "./MyComponent.vue";
6062
6163
6264
export default defineComponent({
6365
name: "HelloWorld",
6466
components: {
6567
sfcExampleVue,
68+
MyComponent
6669
},
6770
data: () => ({
6871
show: true
@@ -78,6 +81,18 @@ export default defineComponent({
7881
]
7982
})
8083
},
84+
createCustomComponentDialog(){
85+
this.$dialog.create({
86+
customComponent: {
87+
component: MyComponent,
88+
props: { message: "Hello world!" }
89+
},
90+
dialogOptions: {
91+
width: "600px",
92+
persistent: true
93+
}
94+
})
95+
},
8196
successDialog(){
8297
this.$dialog.success("Hello world!", "My success dialog")
8398
},
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<template>
2+
<h1 @click="close()">{{message}}</h1>
3+
</template>
4+
5+
<script>
6+
import { defineEmits } from 'vue'
7+
export default {
8+
name: 'MyComponent',
9+
props: {
10+
message: {
11+
type: String,
12+
required: false
13+
}
14+
},
15+
methods: {
16+
close() {
17+
this.$emit('closeDialog', false)
18+
}
19+
}
20+
}
21+
</script>
22+
23+
<style>
24+
25+
</style>

src/Dialog.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@ export function createDialog(options: CreateDialogOptions) {
2222
try {
2323
const div = document.createElement('div');
2424

25-
if (!isNotEmptyAndNotNull(options.title)) throw new Error('title is required');
26-
if (!isNotEmptyAndNotNull(options.text)) throw new Error('text is required');
25+
if (!options.customComponent) {
26+
if (!isNotEmptyAndNotNull(options.title)) throw new Error('title is required');
27+
if (!isNotEmptyAndNotNull(options.text)) throw new Error('text is required');
28+
} else {
29+
options.title = options.title || '';
30+
options.text = options.text || '';
31+
}
2732

2833
if (options.buttons) {
2934
options.buttons.forEach(validateButton);
@@ -35,7 +40,9 @@ export function createDialog(options: CreateDialogOptions) {
3540
text: options.text,
3641
buttons: options.buttons,
3742
level: options.level,
38-
dialogOptions: PluginContext.getPluginOptions().defaults?.dialog?.component || undefined,
43+
customComponent: options.customComponent,
44+
dialogOptions:
45+
PluginContext.getPluginOptions().defaults?.dialog?.component || options.dialogOptions || undefined,
3946
cardOptions: options.cardOptions ||
4047
PluginContext.getPluginOptions().defaults?.dialog?.card || {
4148
location: 'center center',

src/components/Dialog.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
2-
import { DialogButton } from "types";
3-
import { computed, defineComponent, reactive, ref } from "vue";
2+
import { ComponentOptions, DialogButton } from "types";
3+
import { Component, computed, defineComponent, getCurrentInstance, onMounted, PropType, reactive, ref } from "vue";
44
import { VDialog } from 'vuetify/lib/components/index.mjs'
55
import Card from './Card.vue'
66
@@ -31,6 +31,10 @@ const props = defineProps({
3131
dialogOptions: {
3232
type: Object,
3333
default: () => ({})
34+
},
35+
customComponent: {
36+
type: Object as PropType<ComponentOptions>,
37+
required: false
3438
}
3539
})
3640
@@ -54,7 +58,11 @@ function close(buttonKey: string | boolean){
5458
v-model="showDialog"
5559
v-bind="dialogOptions"
5660
>
61+
<template v-if="customComponent">
62+
<component :is="customComponent.component" v-bind="customComponent.props" @closeDialog="close" ref="custom-component" />
63+
</template>
5764
<Card
65+
v-else
5866
v-bind="cardOptions"
5967
:title="title"
6068
:text="text"

src/components/MyComponent.vue

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<template>
2+
<h1 @click="close()">Coucou !</h1>
3+
</template>
4+
5+
<script>
6+
import { defineEmits } from 'vue'
7+
export default {
8+
name: 'MyComponent',
9+
// setup() {
10+
// const emits = defineEmits(['closeDialog']);
11+
// return {
12+
// emits
13+
// }
14+
// },
15+
methods: {
16+
close() {
17+
this.$emit('closeDialog', false)
18+
}
19+
}
20+
}
21+
</script>
22+
23+
<style>
24+
25+
</style>

src/index.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { App, Plugin } from 'vue';
1+
import type { App, Component, Plugin } from 'vue';
22
import { VBottomSheet } from 'vuetify/labs/VBottomSheet';
33
import { VBtn } from 'vuetify/lib/components/VBtn/index.mjs';
44
import { VCard } from 'vuetify/lib/components/VCard/index.mjs';
@@ -22,11 +22,18 @@ export type Level = 'warning' | 'error' | 'info' | 'success';
2222

2323
export type DialogButton = Omit<Omit<VBtn['$props'], 'text'>, 'key'> & { title: string; key: string | boolean };
2424

25+
export type ComponentOptions = {
26+
component: Component;
27+
props: any;
28+
};
29+
2530
export type CreateDialogOptions = {
2631
title: string;
2732
text: string;
2833
buttons?: DialogButton[];
2934
level?: Level;
35+
customComponent?: ComponentOptions;
36+
dialogOptions?: VDialog['$props'];
3037
cardOptions?: VCard['$props'];
3138
};
3239

src/types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Plugin } from 'vue';
1+
import { Component, Plugin } from 'vue';
22
import { VBottomSheet } from 'vuetify/labs/VBottomSheet';
33
import { VBtn } from 'vuetify/lib/components/VBtn/index.mjs';
44
import { VCard } from 'vuetify/lib/components/VCard/index.mjs';
@@ -22,11 +22,18 @@ export type Level = 'warning' | 'error' | 'info' | 'success';
2222

2323
export type DialogButton = Omit<Omit<VBtn['$props'], 'text'>, 'key'> & { title: string; key: string | boolean };
2424

25+
export type ComponentOptions = {
26+
component: Component;
27+
props: any;
28+
};
29+
2530
export type CreateDialogOptions = {
2631
title: string;
2732
text: string;
2833
buttons?: DialogButton[];
2934
level?: Level;
35+
customComponent?: ComponentOptions;
36+
dialogOptions?: VDialog['$props'];
3037
cardOptions?: VCard['$props'];
3138
};
3239

0 commit comments

Comments
 (0)