@@ -1724,6 +1724,7 @@ class Component {
1724
1724
this . defaultDebounce = 150 ;
1725
1725
this . backendRequest = null ;
1726
1726
this . pendingActions = [ ] ;
1727
+ this . pendingFiles = { } ;
1727
1728
this . isRequestPending = false ;
1728
1729
this . requestDebounceTimeout = null ;
1729
1730
this . children = new Map ( ) ;
@@ -1801,6 +1802,9 @@ class Component {
1801
1802
this . debouncedStartRequest ( debounce ) ;
1802
1803
return promise ;
1803
1804
}
1805
+ files ( key , fileList ) {
1806
+ this . pendingFiles [ key ] = fileList ;
1807
+ }
1804
1808
render ( ) {
1805
1809
const promise = this . nextRequestPromise ;
1806
1810
this . tryStartingRequest ( ) ;
@@ -1900,7 +1904,7 @@ class Component {
1900
1904
const thisPromiseResolve = this . nextRequestPromiseResolve ;
1901
1905
this . resetPromise ( ) ;
1902
1906
this . unsyncedInputsTracker . resetUnsyncedFields ( ) ;
1903
- this . backendRequest = this . backend . makeRequest ( this . valueStore . getOriginalProps ( ) , this . pendingActions , this . valueStore . getDirtyProps ( ) , this . getChildrenFingerprints ( ) , this . valueStore . getUpdatedPropsFromParent ( ) , { } ) ;
1907
+ this . backendRequest = this . backend . makeRequest ( this . valueStore . getOriginalProps ( ) , this . pendingActions , this . valueStore . getDirtyProps ( ) , this . getChildrenFingerprints ( ) , this . valueStore . getUpdatedPropsFromParent ( ) , this . pendingFiles ) ;
1904
1908
this . hooks . triggerHook ( 'loading.state:started' , this . element , this . backendRequest ) ;
1905
1909
this . pendingActions = [ ] ;
1906
1910
this . valueStore . flushDirtyPropsToPending ( ) ;
@@ -2668,6 +2672,7 @@ class LiveControllerDefault extends Controller {
2668
2672
{ event : 'change' , callback : ( event ) => this . handleChangeEvent ( event ) } ,
2669
2673
{ event : 'live:connect' , callback : ( event ) => this . handleConnectedControllerEvent ( event ) } ,
2670
2674
] ;
2675
+ this . pendingFiles = { } ;
2671
2676
}
2672
2677
initialize ( ) {
2673
2678
this . handleDisconnectedChildControllerEvent = this . handleDisconnectedChildControllerEvent . bind ( this ) ;
@@ -2716,6 +2721,7 @@ class LiveControllerDefault extends Controller {
2716
2721
const directives = parseDirectives ( rawAction ) ;
2717
2722
let debounce = false ;
2718
2723
directives . forEach ( ( directive ) => {
2724
+ let pendingFiles = { } ;
2719
2725
const validModifiers = new Map ( ) ;
2720
2726
validModifiers . set ( 'prevent' , ( ) => {
2721
2727
event . preventDefault ( ) ;
@@ -2731,6 +2737,14 @@ class LiveControllerDefault extends Controller {
2731
2737
validModifiers . set ( 'debounce' , ( modifier ) => {
2732
2738
debounce = modifier . value ? parseInt ( modifier . value ) : true ;
2733
2739
} ) ;
2740
+ validModifiers . set ( 'files' , ( modifier ) => {
2741
+ if ( ! modifier . value ) {
2742
+ pendingFiles = this . pendingFiles ;
2743
+ }
2744
+ else if ( this . pendingFiles [ modifier . value ] ) {
2745
+ pendingFiles [ modifier . value ] = this . pendingFiles [ modifier . value ] ;
2746
+ }
2747
+ } ) ;
2734
2748
directive . modifiers . forEach ( ( modifier ) => {
2735
2749
var _a ;
2736
2750
if ( validModifiers . has ( modifier . name ) ) {
@@ -2740,6 +2754,10 @@ class LiveControllerDefault extends Controller {
2740
2754
}
2741
2755
console . warn ( `Unknown modifier ${ modifier . name } in action "${ rawAction } ". Available modifiers are: ${ Array . from ( validModifiers . keys ( ) ) . join ( ', ' ) } .` ) ;
2742
2756
} ) ;
2757
+ for ( const [ key , files ] of Object . entries ( pendingFiles ) ) {
2758
+ this . component . files ( key , files ) ;
2759
+ delete this . pendingFiles [ key ] ;
2760
+ }
2743
2761
this . component . action ( directive . action , directive . named , debounce ) ;
2744
2762
if ( getModelDirectiveFromElement ( event . currentTarget , false ) ) {
2745
2763
this . pendingActionTriggerModelElement = event . currentTarget ;
@@ -2809,12 +2827,23 @@ class LiveControllerDefault extends Controller {
2809
2827
this . updateModelFromElementEvent ( target , 'change' ) ;
2810
2828
}
2811
2829
updateModelFromElementEvent ( element , eventName ) {
2830
+ var _a , _b ;
2812
2831
if ( ! elementBelongsToThisComponent ( element , this . component ) ) {
2813
2832
return ;
2814
2833
}
2815
2834
if ( ! ( element instanceof HTMLElement ) ) {
2816
2835
throw new Error ( 'Could not update model for non HTMLElement' ) ;
2817
2836
}
2837
+ if ( element instanceof HTMLInputElement
2838
+ && element . type === 'file' ) {
2839
+ const key = ( _a = element . dataset . model ) !== null && _a !== void 0 ? _a : element . name ;
2840
+ if ( ( _b = element . files ) === null || _b === void 0 ? void 0 : _b . length ) {
2841
+ this . pendingFiles [ key ] = element . files ;
2842
+ }
2843
+ else if ( this . pendingFiles [ key ] ) {
2844
+ delete this . pendingFiles [ key ] ;
2845
+ }
2846
+ }
2818
2847
const modelDirective = getModelDirectiveFromElement ( element , false ) ;
2819
2848
if ( ! modelDirective ) {
2820
2849
return ;
0 commit comments