1- import { Component , Element , Host , h } from '@stencil/core' ;
1+ import { Component , Prop , Element , Event , EventEmitter , Host , h } from '@stencil/core' ;
22
33/**
44 * The Form component may optionally be used to wrap a native HTML form, providing enhanced functionality and support
@@ -13,39 +13,90 @@ import { Component, Element, Host, h } from '@stencil/core';
1313export class CbpForm {
1414
1515 private form : HTMLFormElement ;
16+ private enhancedFileInputs : HTMLCbpFileInputElement [ ] = [ ] ;
17+ private files : object = { } ;
1618
1719 @Element ( ) host : HTMLCbpFormElement ;
18-
19- handleSubmit ( e ) {
20- /*
21- Update FormData (or create a copy) with fields not supported natively:
22- * File input (allowing manipulation of FileList)
23- */
24- console . log ( 'cbp-form - Submit event: ' , e ) ;
25- e . preventDefault ( ) ;
26-
27- // Empty FormData object
28- //let formData = new FormData();
29- // FormData object populated from an existing form
30- let formData = new FormData ( this ?. form ) ;
3120
32- console . log ( 'cbp-form - formData: ' , formData ) ;
33- // Spreading the formData as an array seems to give the same results as above.
34- console . log ( 'formData (array spread): ' , [ ... formData ] ) ;
35- }
21+ /** When specified, applies preventDefault() to the submit event and emits a custom event with the formData to hand off to the application. */
22+ @ Prop ( ) preventSubmit : boolean ;
23+
24+ @ Event ( ) suppressedSubmit : EventEmitter ;
3625
26+
3727 handleReset ( ) {
3828 // Call reset methods on form fields that do not natively support it.
3929 const SpecialCases : any = this . form . querySelectorAll ( 'cbp-dropdown,cbp-slider,cbp-segmented-button-group,cbp-checkbox,cbp-radio,cbp-toggle,cbp-file-input' ) ;
4030 SpecialCases . forEach ( item => {
4131 item . reset ( ) ;
4232 } ) ;
33+ // reset enhanced/multi-file inputs to []
34+ Object . keys ( this . files ) . forEach ( key => {
35+ this . files [ key ] = [ ] ;
36+ } ) ;
37+ }
38+
39+ handleSubmit ( e ) {
40+ const form = e . srcElement ;
41+ // FormData object populated from an existing form
42+ let formData = new FormData ( form ) ;
43+
44+ e . preventDefault ( ) ;
45+
46+ // Add files from enhanced/multi-file inputs
47+ formData = this . addFiles ( formData ) ;
48+
49+ //console.log('resulting formData (array spread): ',[...formData]);
50+
51+ // If the form submission is prevented, emit an event with the data instead
52+ if ( this . preventSubmit ) {
53+ this . suppressedSubmit . emit ( {
54+ host : this . host ,
55+ form : form ,
56+ formData : formData ,
57+ nativeEvent : e
58+ } ) ;
59+ }
60+ // otherwise submit after updating the formData
61+ else form . submit ( ) ;
62+ }
63+
64+ addFiles ( formData ) {
65+ /*
66+ Update FormData (or create a copy) with fields not supported natively:
67+ File input (multiple+enhanced, allowing manipulation of FileList)
68+ */
69+ Object . keys ( this . files ) . forEach ( key => {
70+ if ( this . files ?. [ `${ key } ` ] ?. length > 0 ) {
71+ // delete the empty key if there are files specified
72+ formData . delete ( key ) ;
73+ // loop over the files and add each as a new entry using append (set overrides the same entry)
74+ this . files ?. [ key ] . forEach ( file => {
75+ formData . append ( key , file ) ;
76+ } ) ;
77+ }
78+ formData [ `${ key } ` ] = this . files [ `${ key } ` ] ;
79+ } ) ;
80+ return formData ;
81+ }
82+
83+ handleEnhancedFileInput ( e ) {
84+ // Keep tabs on enhanced/multi-file inputs' values
85+ const { name, value} = e . detail ;
86+ this . files [ name ] = value ;
87+ console . log ( 'cbp-form - Tracking enhanced/multi-file input: ' , this . files ) ;
4388 }
4489
45- componentWillLoad ( ) {
90+ componentWillLoad ( ) {
4691 this . form = this . host . querySelector ( 'form' ) ;
4792 this . form . addEventListener ( 'submit' , e => this . handleSubmit ( e ) ) ;
4893 this . form . addEventListener ( 'reset' , ( ) => this . handleReset ( ) ) ;
94+
95+ // Listen for changes to enhanced/multi-file inputs
96+ this . enhancedFileInputs = Array . from ( this . host . querySelectorAll ( 'cbp-file-input[multiple]' ) ) ;
97+ this . enhancedFileInputs . forEach ( item => {
98+ item . addEventListener ( 'valueChange' , e => this . handleEnhancedFileInput ( e ) ) ;
99+ } ) ;
49100 }
50101
51102 render ( ) {
0 commit comments