0
0
mirror of https://github.com/wagtail/wagtail.git synced 2024-11-25 05:02:57 +01:00

DialogController add support for notifyTargets

- Allowing the dispatching of events to internal targets for key modal events
- See ##11029
This commit is contained in:
Chiemezuo 2023-10-17 12:21:48 +01:00 committed by LB (Ben Johnston)
parent 75fb953754
commit 29d73a3b68
4 changed files with 96 additions and 3 deletions

View File

@ -115,6 +115,7 @@ Changelog
* Maintenance: Add generic `InspectView` to `ModelViewSet` (Sage Abdullah)
* Maintenance: Migrate select all on focus/click behavior to Stimulus, used on the image URL generator (Chiemezuo Akujobi)
* Maintenance: Add support for a `reset` method to support Stimulus driven dynamic field resets via the `w-action` controller (Chiemezuo Akujobi)
* Maintenance: Add support for a `notify` target on the Stimulus dialog for dispatching events internally (Chiemezuo Akujobi)
5.1.3 (xx.xx.20xx) - IN DEVELOPMENT
~~~~~~~~~~~~~~~~~~

View File

@ -136,4 +136,74 @@ describe('DialogController', () => {
expect(hiddenListener).toHaveBeenCalled();
});
});
describe('dispatching events internally via notify targets', () => {
const eventHandler = jest.fn();
beforeEach(() => {
application?.stop();
document.body.innerHTML = `
<section>
<div
id="dialog-container"
aria-hidden="true"
data-controller="w-dialog"
data-action="w-dialog:hide->w-dialog#hide w-dialog:show->w-dialog#show"
>
<div role="document">
<div id="dialog-body" data-w-dialog-target="body">
<h3>Content</h3>
<div data-w-dialog-target="notify" id="inner-content"></div>
</div>
</div>
<div data-w-dialog-target="notify" id="outer-content"></div>
</div>
</section>`;
const doc = document.getElementById('inner-content');
doc.addEventListener('w-dialog:shown', eventHandler);
doc.addEventListener('w-dialog:hidden', eventHandler);
doc.addEventListener('w-dialog:ready', eventHandler);
application = new Application();
application.register('w-dialog', DialogController);
application.start();
});
afterEach(() => {
document.body.innerHTML = '';
jest.clearAllMocks();
});
it('should dispatch events to notify targets', async () => {
const dialogContainer = document.getElementById('dialog-container');
dialogContainer.dispatchEvent(new CustomEvent('w-dialog:show'));
// twice, because of show and ready
expect(eventHandler).toHaveBeenCalledTimes(2);
// checking the first mock function called
expect(eventHandler.mock.calls[0][0]).toMatchObject({
type: 'w-dialog:ready',
bubbles: false,
});
// checking the second mock function called
expect(eventHandler.mock.calls[1][0]).toMatchObject({
type: 'w-dialog:shown',
bubbles: false,
});
dialogContainer.dispatchEvent(new CustomEvent('w-dialog:hide'));
// called once again, therefore 3 times
expect(eventHandler).toHaveBeenCalledTimes(3);
// checking the third mock function called
expect(eventHandler.mock.calls[2][0]).toMatchObject({
type: 'w-dialog:hidden',
bubbles: false,
});
});
});
});

View File

@ -21,11 +21,13 @@ export class DialogController extends Controller<HTMLElement> {
theme: { default: '', type: String },
};
static targets = ['body'];
static targets = ['body', 'notify'];
declare dialog: A11yDialog;
declare readonly bodyTarget: HTMLElement;
declare readonly themeValue: string;
/** Optional targets that will be dispatched events for key dialog events. */
declare readonly notifyTargets: HTMLElement[];
connect() {
this.dialog = new A11yDialog(this.element);
@ -34,13 +36,32 @@ export class DialogController extends Controller<HTMLElement> {
this.dialog
.on('show', () => {
if (!isFloating) document.documentElement.style.overflowY = 'hidden';
this.dispatch('shown', { detail });
this.dispatch('shown', { detail, cancelable: false });
this.notifyTargets.forEach((target) => {
this.dispatch('shown', {
target,
bubbles: false,
cancelable: false,
});
});
})
.on('hide', () => {
if (!isFloating) document.documentElement.style.overflowY = '';
this.dispatch('hidden', { detail });
this.dispatch('hidden', { detail, cancelable: false });
this.notifyTargets.forEach((target) => {
this.dispatch('hidden', {
target,
bubbles: false,
cancelable: false,
});
});
});
this.dispatch('ready', { detail });
if (this.notifyTargets && Array.isArray(this.notifyTargets)) {
this.notifyTargets.forEach((target) => {
this.dispatch('ready', { target, bubbles: false, cancelable: false });
});
}
return this.dialog;
}

View File

@ -146,6 +146,7 @@ This feature was developed by Paarth Agarwal and Thibaud Colas as part of the Go
* Add generic `InspectView` to `ModelViewSet` (Sage Abdullah)
* Migrate select all on focus/click behavior to Stimulus, used on the image URL generator (Chiemezuo Akujobi)
* Add support for a `reset` method to support Stimulus driven dynamic field resets via the `w-action` controller (Chiemezuo Akujobi)
* Add support for a `notify` target on the Stimulus dialog for dispatching events internally (Chiemezuo Akujobi)
## Upgrade considerations - changes affecting all projects