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:
parent
75fb953754
commit
29d73a3b68
@ -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
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
@ -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,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user