kopia lustrzana https://github.com/wagtail/wagtail
				
				
				
			DialogController add support for notifyTargets
- Allowing the dispatching of events to internal targets for key modal events - See ##11029pull/11073/head^2
							rodzic
							
								
									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 | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Chiemezuo
						Chiemezuo