@@ -432,7 +432,19 @@ class UITemplateSlot {
432432 for ( const attr of node . attributes ) {
433433 if ( attr . name . startsWith ( prefix ) ) {
434434 const eventType = attr . name . slice ( prefix . length ) ;
435- const handlerName = attr . value || eventType ;
435+ const parsed = TemplateParser . parseEventEffect ( attr . value , eventType ) ;
436+ if ( ! parsed ) {
437+ log . warn ( "UITemplateSlot.FindEvent: invalid event effect, details" , {
438+ eventType,
439+ effect : attr . value ,
440+ } ) ;
441+ toRemove . push ( attr . name ) ;
442+ continue ;
443+ }
444+ const handlerName =
445+ parsed . mode === "handler"
446+ ? parsed . handlerName || eventType
447+ : `!${ parsed . publishEvent } :${ parsed . binding ?. sourceKey || "data" } ` ;
436448 toRemove . push ( attr . name ) ;
437449
438450 const slot = new UIEventTemplateSlot (
@@ -441,6 +453,9 @@ class UITemplateSlot {
441453 UITemplateSlot . Path ( node , parent , [ i ] ) ,
442454 eventType ,
443455 handlerName ,
456+ parsed . mode ,
457+ parsed . publishEvent ,
458+ parsed . binding ,
444459 ) ;
445460
446461 if ( ! res [ handlerName ] ) res [ handlerName ] = [ ] ;
@@ -715,14 +730,26 @@ class UIAttributeSlot {
715730// - `eventType`: string - DOM event type (e.g., "click")
716731// - `handlerName`: string - behavior method name to call
717732class UIEventTemplateSlot {
718- constructor ( node , parent , path , eventType , handlerName ) {
733+ constructor (
734+ node ,
735+ parent ,
736+ path ,
737+ eventType ,
738+ handlerName ,
739+ mode = "handler" ,
740+ publishEvent = null ,
741+ binding = null ,
742+ ) {
719743 this . node = node ;
720744 this . parent = parent ;
721745 this . path = path ;
722746 this . rootIndex = path [ 0 ] ;
723747 this . tailPath = path . length > 1 ? path . slice ( 1 ) : null ;
724748 this . eventType = eventType ;
725749 this . handlerName = handlerName ;
750+ this . mode = mode ;
751+ this . publishEvent = publishEvent ;
752+ this . binding = binding ;
726753 }
727754
728755 resolve ( nodes ) {
@@ -747,6 +774,9 @@ class UIEventSlot {
747774 this . parent = parent ;
748775 this . eventType = template . eventType ;
749776 this . handlerName = template . handlerName ;
777+ this . mode = template . mode ;
778+ this . publishEvent = template . publishEvent ;
779+ this . binding = template . binding ;
750780 }
751781}
752782// Class: UITemplate
@@ -1844,6 +1874,32 @@ class UIInstance {
18441874
18451875 // Binds event slot with explicit event type.
18461876 _bindEvent ( name , target , handler = this . template . behavior ?. [ name ] ) {
1877+ if ( target . mode === "publish" && target . publishEvent ) {
1878+ const listener = ( _event ) => {
1879+ const data = this . data || { } ;
1880+ let payload = data ;
1881+ if ( target . binding ?. sourceKey ) {
1882+ payload = expand ( resolveSourceValue ( data , target . binding . sourceKey ) ) ;
1883+ if ( target . binding . processors ?. length ) {
1884+ payload = applyNamedProcessors (
1885+ this ,
1886+ data ,
1887+ payload ,
1888+ target . binding . processors ,
1889+ target . binding . sourceKey ,
1890+ ) ;
1891+ }
1892+ }
1893+ this . pub ( target . publishEvent , payload ) ;
1894+ } ;
1895+ target . node . addEventListener ( target . eventType , listener ) ;
1896+ this . _domListeners . push ( {
1897+ node : target . node ,
1898+ type : target . eventType ,
1899+ handler : listener ,
1900+ } ) ;
1901+ return ;
1902+ }
18471903 if ( handler ) {
18481904 const listener = ( event ) => {
18491905 const result = handler ( this , this . data || { } , event ) ;
0 commit comments