Skip to content

Commit 77ee949

Browse files
authored
Dispatch an event to a modal being closed before closing it, so that the modal can prevent it based on its state (#466)
1 parent 277c6c8 commit 77ee949

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,29 @@ By default, the modal will close when you click outside the modal. If you want t
306306
}
307307
```
308308

309+
## Preventing closing the modal on Escape or on click away based on the modal state
310+
311+
When a modal is closed on Escape or click away, `closingModalOnEscape` and `closingModalOnClickAway` are issued. Handle these events to prevent closing a modal based on its state, for example, if there are uncommitted changes.
312+
313+
For example, if a modal has a `isDirty` property, it could have the following handler:
314+
315+
```
316+
@script
317+
<script>
318+
$wire.on('closingModalOnEscape', data => {
319+
if ($wire.isDirty && !confirm('{{ __('You have unsaved changes. Are you sure you want to close this dialog?') }}')) {
320+
data.closing = false;
321+
}
322+
});
323+
$wire.on('closingModalOnClickAway', data => {
324+
if ($wire.isDirty && !confirm('{{ __('You have unsaved changes. Are you sure you want to close this dialog?') }}')) {
325+
data.closing = false;
326+
}
327+
});
328+
</script>
329+
@endscript
330+
```
331+
309332
## Skipping previous modals
310333
In some cases you might want to skip previous modals. For example:
311334
1. Team overview modal

resources/js/modal.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ window.LivewireUIModal = () => {
1616
return;
1717
}
1818

19+
if (!this.closingModal('closingModalOnEscape')) {
20+
return;
21+
}
22+
1923
let force = this.getActiveComponentModalAttribute('closeOnEscapeIsForceful') === true;
2024
this.closeModal(force);
2125
},
@@ -24,8 +28,24 @@ window.LivewireUIModal = () => {
2428
return;
2529
}
2630

31+
if (!this.closingModal('closingModalOnClickAway')) {
32+
return;
33+
}
34+
2735
this.closeModal(true);
2836
},
37+
closingModal(eventName) {
38+
const componentName = this.$wire.get('components')[this.activeComponent].name;
39+
40+
var params = {
41+
id: this.activeComponent,
42+
closing: true,
43+
};
44+
45+
Livewire.dispatchTo(componentName, eventName, params);
46+
47+
return params.closing;
48+
},
2949
closeModal(force = false, skipPreviousModals = 0, destroySkipped = false) {
3050
if(this.show === false) {
3151
return;

0 commit comments

Comments
 (0)