22 PHX_REF_LOADING ,
33 PHX_REF_LOCK ,
44 PHX_REF_SRC ,
5+ PHX_PENDING_REFS ,
56 PHX_EVENT_CLASSES ,
67 PHX_DISABLED ,
78 PHX_READONLY ,
@@ -42,6 +43,12 @@ export default class ElementRef {
4243
4344 maybeUndo ( ref , phxEvent , eachCloneCallback ) {
4445 if ( ! this . isWithin ( ref ) ) {
46+ // we cannot undo the lock / loading now, as there is a newer one already set;
47+ // we need to store the original ref we tried to send the undo event later
48+ DOM . updatePrivate ( this . el , PHX_PENDING_REFS , [ ] , ( pendingRefs ) => {
49+ pendingRefs . push ( ref ) ;
50+ return pendingRefs ;
51+ } ) ;
4552 return ;
4653 }
4754
@@ -51,6 +58,29 @@ export default class ElementRef {
5158 // undo loading states
5259 this . undoLoading ( ref , phxEvent ) ;
5360
61+ // ensure undo events are fired for pending refs that
62+ // are resolved by the current ref, otherwise we'd leak event listeners
63+ DOM . updatePrivate ( this . el , PHX_PENDING_REFS , [ ] , ( pendingRefs ) => {
64+ return pendingRefs . filter ( ( pendingRef ) => {
65+ let opts = {
66+ detail : { ref : pendingRef , event : phxEvent } ,
67+ bubbles : true ,
68+ cancelable : false ,
69+ } ;
70+ if ( this . loadingRef && this . loadingRef > pendingRef ) {
71+ this . el . dispatchEvent (
72+ new CustomEvent ( `phx:undo-loading:${ pendingRef } ` , opts ) ,
73+ ) ;
74+ }
75+ if ( this . lockRef && this . lockRef > pendingRef ) {
76+ this . el . dispatchEvent (
77+ new CustomEvent ( `phx:undo-lock:${ pendingRef } ` , opts ) ,
78+ ) ;
79+ }
80+ return pendingRef > ref ;
81+ } ) ;
82+ } ) ;
83+
5484 // clean up if fully resolved
5585 if ( this . isFullyResolvedBy ( ref ) ) {
5686 this . el . removeAttribute ( PHX_REF_SRC ) ;
0 commit comments