Skip to content

Commit 5560ea6

Browse files
pgbrosspgbross
authored andcommitted
feat(mdc-dialog): Support v-model for open/close dialog
1 parent 7ce4311 commit 5560ea6

File tree

3 files changed

+139
-102
lines changed

3 files changed

+139
-102
lines changed

components/dialog/README.md

Lines changed: 90 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,90 @@
1-
## Usage
2-
3-
```html
4-
<mdc-dialog ref="dialog"
5-
title="Title" accept="Accept" cancel="Decline"
6-
@accept="onAccept" @cancel="onDecline"
7-
>{{ dialogText }}</mdc-dialog>
8-
```
9-
10-
```javascript
11-
var vm = new Vue({
12-
data: {
13-
dialogText: 'Lorem ipsum dolor sit amet, ...',
14-
},
15-
methods: {
16-
showDialog () {
17-
this.$refs.dialog.show()
18-
},
19-
onAccept () {
20-
console.log('accepted')
21-
},
22-
onDecline () {
23-
console.log('declined')
24-
},
25-
}
26-
})
27-
```
28-
29-
### props
30-
31-
| props | Type | Default | Description |
32-
|-------|------|---------|-------------|
33-
|`title`|String| required | the dialog title |
34-
|`accept`|String|`'Ok'`| the dialog accept button text |
35-
|`accept-disabled`|String|`'Ok'`| the dialog accept button text |
36-
|`cancel`| String| `'cancel'`| the dialog cancel button text |
37-
|`scrollable`| Boolean| false | whether the dialog is scrollable |
38-
|`accent`| Boolean| false | set accented style to the footer buttons |
39-
40-
### events
41-
42-
| props | args | Description |
43-
|---------|------|--------------|
44-
|`@accept`| none | emitted when dialog is accepted |
45-
|`@cancel`| none | emitted when dialog is cancelled |
46-
|`@validate`| accept | emmited before the dialog is accepted _(*)_ |
47-
48-
> Note that if you listen to the @validate event, then You must call
49-
the accept argument to finally close the box. Use `accept(false)` to
50-
prevent emitting the `accept` event and just close.
51-
52-
### Custom validation logic
53-
54-
You can use the `accept-disabled` property to prevent the dialog to close
55-
when the accept button is clicked.
56-
57-
```html
58-
<mdc-dialog ref="dialog" title="Dialog" accept="Accept" cancel="Decline"
59-
:accept-disabled="isThisNotAcceptable"
60-
>Lorem ipsum dolor sit amet</mdc-dialog>
61-
```
62-
63-
Or use the `@validate` event to trigger your own validation logic as follow:
64-
65-
```html
66-
<mdc-dialog ref="dialog" title="Dialog" accept="Accept" cancel="Decline"
67-
@validate="onValidate"
68-
>Lorem ipsum dolor sit amet</mdc-dialog>
69-
```
70-
71-
```javascript
72-
export default {
73-
methods:{
74-
onValidate ({accept}) {
75-
let isValid = false
76-
// custom validation logic here
77-
// ..
78-
if (isValid) {
79-
accept()
80-
}
81-
}
82-
}
83-
}
84-
```
85-
86-
### Reference
87-
88-
<https://material.io/components/web/catalog/dialogs>
1+
## Usage
2+
3+
```html
4+
<mdc-button raised @click="open=!open">Show dialog</mdc-button>
5+
<mdc-dialog v-model="open"
6+
title="Title" accept="Accept" cancel="Decline"
7+
@accept="onAccept" @cancel="onDecline">
8+
{{ dialogText }}
9+
</mdc-dialog>
10+
```
11+
12+
```javascript
13+
var vm = new Vue({
14+
data: {
15+
dialogText: 'Lorem ipsum dolor sit amet, ...',
16+
open: false,
17+
},
18+
methods: {
19+
onAccept() {
20+
console.log('accepted');
21+
},
22+
onDecline() {
23+
console.log('declined');
24+
},
25+
},
26+
});
27+
```
28+
29+
### props
30+
31+
| props | Type | Default | Description |
32+
| ----------------- | ------- | ---------- | ---------------------------------------- |
33+
| `open` | Boolean | false | optional v-model when true opens dialog |
34+
| `title` | String | required | the dialog title |
35+
| `accept` | String | `'Ok'` | the dialog accept button text |
36+
| `accept-disabled` | String | `'Ok'` | the dialog accept button text |
37+
| `cancel` | String | `'cancel'` | the dialog cancel button text |
38+
| `scrollable` | Boolean | false | whether the dialog is scrollable |
39+
| `accent` | Boolean | false | set accented style to the footer buttons |
40+
41+
### events
42+
43+
| props | args | Description |
44+
| ----------- | ------- | ------------------------------------------------------- |
45+
| `@change` | Boolean | notify v-model/listeners that drawer state has changed. |
46+
| `@accept` | none | emitted when dialog is accepted |
47+
| `@cancel` | none | emitted when dialog is cancelled |
48+
| `@validate` | accept | emmited before the dialog is accepted _(\*)_ |
49+
50+
> Note that if you listen to the @validate event, then You must call
51+
> the accept argument to finally close the box. Use `accept(false)` to
52+
> prevent emitting the `accept` event and just close.
53+
54+
### Custom validation logic
55+
56+
You can use the `accept-disabled` property to prevent the dialog to close
57+
when the accept button is clicked.
58+
59+
```html
60+
<mdc-dialog ref="dialog" title="Dialog" accept="Accept" cancel="Decline"
61+
:accept-disabled="isThisNotAcceptable"
62+
>Lorem ipsum dolor sit amet</mdc-dialog>
63+
```
64+
65+
Or use the `@validate` event to trigger your own validation logic as follow:
66+
67+
```html
68+
<mdc-dialog ref="dialog" title="Dialog" accept="Accept" cancel="Decline"
69+
@validate="onValidate"
70+
>Lorem ipsum dolor sit amet</mdc-dialog>
71+
```
72+
73+
```javascript
74+
export default {
75+
methods: {
76+
onValidate({ accept }) {
77+
let isValid = false;
78+
// custom validation logic here
79+
// ..
80+
if (isValid) {
81+
accept();
82+
}
83+
},
84+
},
85+
};
86+
```
87+
88+
### Reference
89+
90+
<https://material.io/components/web/catalog/dialogs>

components/dialog/demo.vue

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
<template>
2-
<div class="mdc-demo mdc-demo--container">
2+
<div class="mdc-demo mdc-demo--container">
33

4-
<mdc-dialog ref="dialog" title="Dialog" accept="Accept" cancel="Decline"
5-
@validate="$event.accept()"
6-
>
7-
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
8-
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
9-
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
10-
commodo consequat.
11-
</mdc-dialog>
4+
<mdc-dialog v-model="open" title="Dialog" accept="Accept" cancel="Decline" @validate="$event.accept(false)">
5+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
6+
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex
7+
ea commodo consequat.
8+
</mdc-dialog>
129

13-
<mdc-button raised @click="$refs.dialog.show()">Show Dialog</mdc-button>
10+
<mdc-button raised @click="open=!open">Show Dialog</mdc-button>
1411

15-
</div>
12+
</div>
1613
</template>
14+
15+
<script>
16+
export default {
17+
data() {
18+
return {
19+
open: false,
20+
};
21+
},
22+
};
23+
</script>

components/dialog/mdc-dialog.vue

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,18 @@ import { mdcButton } from '../button';
3939
4040
export default {
4141
name: 'mdc-dialog',
42+
model: {
43+
prop: 'open',
44+
event: 'change',
45+
},
4246
props: {
4347
title: { type: String, required: true },
4448
accept: { type: String, default: 'Ok' },
4549
acceptDisabled: Boolean,
4650
cancel: { type: String, default: 'Cancel' },
4751
accent: Boolean,
4852
scrollable: Boolean,
53+
open: Boolean,
4954
},
5055
components: {
5156
mdcButton: mdcButton,
@@ -95,8 +100,14 @@ export default {
95100
this.$refs.surface.addEventListener('transitionend', handler),
96101
deregisterTransitionEndHandler: handler =>
97102
this.$refs.surface.removeEventListener('transitionend', handler),
98-
notifyAccept: () => this.$emit('accept'),
99-
notifyCancel: () => this.$emit('cancel'),
103+
notifyAccept: () => {
104+
this.$emit('change', false);
105+
this.$emit('accept');
106+
},
107+
notifyCancel: () => {
108+
this.$emit('change', false);
109+
this.$emit('cancel');
110+
},
100111
trapFocusOnSurface: () => this.focusTrap.activate(),
101112
untrapFocusOnSurface: () => this.focusTrap.deactivate(),
102113
isDialog: el => this.$refs.surface === el,
@@ -111,14 +122,31 @@ export default {
111122
beforeDestroy() {
112123
this.foundation.destroy();
113124
},
125+
watch: { open: 'onOpen_' },
114126
methods: {
127+
onOpen_(value) {
128+
if (value) {
129+
this.foundation.open();
130+
} else {
131+
this.foundation.close();
132+
}
133+
},
115134
onCancel() {
116135
this.foundation.cancel(true);
117136
},
118137
onAccept() {
119138
if (this.$listeners['validate']) {
120139
this.$emit('validate', {
121-
accept: (notify = true) => this.foundation.accept(notify),
140+
accept: (notify = true) => {
141+
// if notify = false, the dialog will close
142+
// but the notifyAccept method will not be called
143+
// so we need to notify listeners the open state
144+
// is changing.
145+
if (!notify) {
146+
this.$emit('change', false);
147+
}
148+
this.foundation.accept(notify);
149+
},
122150
});
123151
} else {
124152
this.foundation.accept(true);

0 commit comments

Comments
 (0)