@@ -377,13 +377,25 @@ export const CrudMixin = (superClass) =>
377377 return this . __fields ;
378378 }
379379
380+ /** @private */
381+ get _editor ( ) {
382+ return this . shadowRoot . querySelector ( '#editor' ) ;
383+ }
384+
385+ /** @private */
386+ get _scroller ( ) {
387+ return this . shadowRoot . querySelector ( '#scroller' ) ;
388+ }
389+
390+ /** @private */
391+ get _dialogMode ( ) {
392+ return this . editorPosition === '' || this . _fullscreen ;
393+ }
394+
380395 /** @protected */
381396 ready ( ) {
382397 super . ready ( ) ;
383398
384- this . $ . dialog . $ . overlay . addEventListener ( 'vaadin-overlay-outside-click' , this . __cancel ) ;
385- this . $ . dialog . $ . overlay . addEventListener ( 'vaadin-overlay-escape-press' , this . __cancel ) ;
386-
387399 this . _gridController = new GridSlotController ( this ) ;
388400 this . addController ( this . _gridController ) ;
389401
@@ -421,6 +433,24 @@ export const CrudMixin = (superClass) =>
421433 this . _confirmDeleteDialog = this . querySelector ( 'vaadin-confirm-dialog[slot="confirm-delete"]' ) ;
422434 }
423435
436+ /** @protected */
437+ updated ( props ) {
438+ super . updated ( props ) ;
439+
440+ // When using dialog mode, hide elements not slotted into the dialog from accessibility tree
441+ if (
442+ props . has ( '_grid' ) ||
443+ props . has ( '_newButton' ) ||
444+ props . has ( 'editorOpened' ) ||
445+ props . has ( 'editorPosition' ) ||
446+ props . has ( '_fullscreen' )
447+ ) {
448+ const hide = this . editorOpened && this . _dialogMode ;
449+ this . __hideElement ( this . _grid , hide ) ;
450+ this . __hideElement ( this . _newButton , hide ) ;
451+ }
452+ }
453+
424454 /**
425455 * @param {boolean } isDirty
426456 * @private
@@ -477,34 +507,31 @@ export const CrudMixin = (superClass) =>
477507 }
478508
479509 if ( opened ) {
480- this . __ensureChildren ( ) ;
481-
482510 // When using bottom / aside editor position,
483511 // auto-focus the editor element on open.
484- if ( this . _form . parentElement === this ) {
485- this . $ . editor . setAttribute ( 'tabindex' , '0' ) ;
486- this . $ . editor . focus ( ) ;
487- } else {
488- this . $ . editor . removeAttribute ( 'tabindex' ) ;
512+ if ( this . _editor ) {
513+ this . _editor . focus ( ) ;
489514 }
490- } else if ( oldOpened ) {
491- // Teleport form and buttons back to light DOM when closing overlay
492- this . __moveChildNodes ( this ) ;
515+
516+ // Wait to set label until header node has updated (observer seems to run after this one)
517+ setTimeout ( ( ) => {
518+ this . __dialogAriaLabel = this . _headerNode . textContent . trim ( ) ;
519+ } ) ;
493520 }
494521
495522 this . __toggleToolbar ( ) ;
496523
497524 // Make sure to reset scroll position
498- this . $ . scroller . scrollTop = 0 ;
525+ if ( this . _scroller ) {
526+ this . _scroller . scrollTop = 0 ;
527+ }
499528 }
500529
501530 /** @private */
502531 __fullscreenChanged ( fullscreen , oldFullscreen ) {
503532 if ( fullscreen || oldFullscreen ) {
504533 this . __toggleToolbar ( ) ;
505534
506- this . __ensureChildren ( ) ;
507-
508535 this . toggleAttribute ( 'fullscreen' , fullscreen ) ;
509536 }
510537 }
@@ -517,66 +544,6 @@ export const CrudMixin = (superClass) =>
517544 }
518545 }
519546
520- /** @private */
521- __moveChildNodes ( target ) {
522- const nodes = [ this . _headerNode , this . _form ] ;
523- const buttons = [ this . _saveButton , this . _cancelButton , this . _deleteButton ] . filter ( Boolean ) ;
524- if ( ! nodes . every ( ( node ) => node instanceof HTMLElement ) ) {
525- return ;
526- }
527-
528- // Teleport header node, form, and the buttons to corresponding slots.
529- // NOTE: order in which buttons are moved matches the order of slots.
530- [ ...nodes , ...buttons ] . forEach ( ( node ) => {
531- // Do not move nodes if the editor position has not changed
532- if ( node . parentNode !== target ) {
533- target . appendChild ( node ) ;
534- }
535- } ) ;
536-
537- // Wait to set label until slotted element has been moved.
538- setTimeout ( ( ) => {
539- this . __dialogAriaLabel = this . _headerNode . textContent . trim ( ) ;
540- } ) ;
541- }
542-
543- /** @private */
544- __shouldOpenDialog ( fullscreen , editorPosition ) {
545- return editorPosition === '' || fullscreen ;
546- }
547-
548- /** @private */
549- __ensureChildren ( ) {
550- if ( this . __shouldOpenDialog ( this . _fullscreen , this . editorPosition ) ) {
551- // Move form to dialog
552- this . __moveChildNodes ( this . $ . dialog . $ . overlay ) ;
553- } else {
554- // Move form to crud
555- this . __moveChildNodes ( this ) ;
556- }
557- }
558-
559- /** @private */
560- __computeDialogOpened ( opened , fullscreen , editorPosition ) {
561- // Only open dialog when editorPosition is "" or fullscreen is set
562- return this . __shouldOpenDialog ( fullscreen , editorPosition ) ? opened : false ;
563- }
564-
565- /** @private */
566- __computeEditorHidden ( opened , fullscreen , editorPosition ) {
567- // Only show editor when editorPosition is "bottom" or "aside"
568- if ( [ 'aside' , 'bottom' ] . includes ( editorPosition ) && ! fullscreen ) {
569- return ! opened ;
570- }
571-
572- return true ;
573- }
574-
575- /** @private */
576- __onDialogOpened ( event ) {
577- this . editorOpened = event . detail . value ;
578- }
579-
580547 /** @private */
581548 __onGridEdit ( event ) {
582549 event . stopPropagation ( ) ;
@@ -620,8 +587,7 @@ export const CrudMixin = (superClass) =>
620587 * @private
621588 */
622589 __formChanged ( form , oldForm ) {
623- if ( oldForm && oldForm . parentElement ) {
624- oldForm . parentElement . removeChild ( oldForm ) ;
590+ if ( oldForm ) {
625591 oldForm . removeEventListener ( 'change' , this . __onFormChange ) ;
626592 oldForm . removeEventListener ( 'input' , this . __onFormChange ) ;
627593 }
@@ -1023,6 +989,17 @@ export const CrudMixin = (superClass) =>
1023989 }
1024990 }
1025991
992+ /** @private */
993+ __hideElement ( element , value ) {
994+ if ( ! element ) return ;
995+
996+ if ( value ) {
997+ element . setAttribute ( 'aria-hidden' , 'true' ) ;
998+ } else {
999+ element . removeAttribute ( 'aria-hidden' ) ;
1000+ }
1001+ }
1002+
10261003 /**
10271004 * Fired when user wants to edit an existing item. If the default is prevented, then
10281005 * a new item is not assigned to the form, giving that responsibility to the app, though
0 commit comments