@@ -33,6 +33,25 @@ import { getTransferItemDirectoryEntry } from '../../files/FileAttachmentContain
3333
3434import { DisableableInput , DisableableInputProps , DisableableInputState } from './DisableableInput' ;
3535
36+ type FileInputData = Map < string , any > | string | undefined ;
37+
38+ export function initializeValue ( initialValue : any ) : { data : FileInputData ; formValue : string | undefined } {
39+ let data : Map < string , any > | string | undefined ;
40+ let formValue : string ;
41+ if ( Map . isMap ( initialValue ) ) {
42+ data = initialValue ;
43+ formValue = initialValue . get ( 'value' ) ;
44+ } else if ( typeof initialValue === 'string' ) {
45+ const trimmedValue = initialValue . trim ( ) ;
46+ if ( trimmedValue !== '' ) {
47+ data = trimmedValue ;
48+ formValue = trimmedValue ;
49+ }
50+ }
51+
52+ return { data, formValue } ;
53+ }
54+
3655export interface FileInputProps extends DisableableInputProps {
3756 acceptedFormats ?: string ;
3857 addLabelAsterisk ?: boolean ;
@@ -54,7 +73,7 @@ export interface FileInputProps extends DisableableInputProps {
5473type FileInputImplProps = FileInputProps & FormsyInjectedProps < any > ;
5574
5675interface State extends DisableableInputState {
57- data : any ;
76+ data : FileInputData ;
5877 error : string ;
5978 file : File ;
6079 isHover : boolean ;
@@ -74,30 +93,21 @@ class FileInputImpl extends DisableableInput<FileInputImplProps, State> {
7493
7594 constructor ( props : FileInputImplProps ) {
7695 super ( props ) ;
77- this . processFiles = this . processFiles . bind ( this ) ;
78- this . onChange = this . onChange . bind ( this ) ;
79- this . onDrag = this . onDrag . bind ( this ) ;
80- this . onDragLeave = this . onDragLeave . bind ( this ) ;
81- this . onDrop = this . onDrop . bind ( this ) ;
82- this . onRemove = this . onRemove . bind ( this ) ;
83- this . setFormValue = this . setFormValue . bind ( this ) ;
8496 this . toggleDisabled = this . toggleDisabled . bind ( this ) ;
8597
8698 this . fileInput = React . createRef < HTMLInputElement > ( ) ;
99+ const { data, formValue } = initializeValue ( props . initialValue ) ;
100+
87101 this . state = {
88- // FileInput only accepts query-shaped row data as the initialValue
89- // as that is what is accepted by FileColumnRenderer. Without this there is likely insufficient
90- // metadata to render and act on the associated file value.
91- data : Map . isMap ( props . initialValue ) ? props . initialValue : undefined ,
92- isHover : false ,
102+ data,
93103 file : null ,
94104 error : '' ,
95105 isDisabled : props . initiallyDisabled ,
106+ isHover : false ,
96107 } ;
97108
98- if ( Map . isMap ( props . initialValue ) ) {
99- // call setValue so to populate form data (for diff compare)
100- props . setValue ?.( props . initialValue . get ( 'value' ) ) ;
109+ if ( formValue ) {
110+ props . setValue ?.( formValue ) ;
101111 }
102112 }
103113
@@ -107,7 +117,7 @@ class FileInputImpl extends DisableableInput<FileInputImplProps, State> {
107117 return this . props . name ?? this . props . queryColumn . fieldKey ;
108118 }
109119
110- processFiles ( fileList : FileList , transferItems ?: DataTransferItemList ) : void {
120+ processFiles = ( fileList : FileList , transferItems ?: DataTransferItemList ) : void => {
111121 const { acceptedFormats, maxFileSize, emptyFileNotAllowed } = this . props ;
112122 if ( fileList . length > 1 ) {
113123 this . setState ( { error : 'Only one file allowed' } ) ;
@@ -139,52 +149,52 @@ class FileInputImpl extends DisableableInput<FileInputImplProps, State> {
139149 return ;
140150 }
141151 this . setFormValue ( file ) ;
142- }
152+ } ;
143153
144- setFormValue ( file : File ) : void {
154+ setFormValue = ( file : File ) : void => {
145155 const { formsy, onChange, setValue } = this . props ;
146156 this . setState ( { data : undefined , file, error : '' } ) ;
147157 onChange ?.( { [ this . getInputName ( ) ] : file } ) ;
148158
149159 if ( formsy ) {
150160 setValue ?.( file ) ;
151161 }
152- }
162+ } ;
153163
154- onChange ( event : React . FormEvent < HTMLInputElement > ) : void {
164+ onChange = ( event : React . FormEvent < HTMLInputElement > ) : void => {
155165 cancelEvent ( event ) ;
156166 this . processFiles ( this . fileInput . current . files ) ;
157- }
167+ } ;
158168
159- onDrag ( event : React . DragEvent < HTMLElement > ) : void {
169+ onDrag = ( event : React . DragEvent < HTMLElement > ) : void => {
160170 cancelEvent ( event ) ;
161171
162172 if ( ! this . state . isHover ) {
163173 this . setState ( { isHover : true } ) ;
164174 }
165- }
175+ } ;
166176
167- onDragLeave ( event : React . DragEvent < HTMLElement > ) : void {
177+ onDragLeave = ( event : React . DragEvent < HTMLElement > ) : void => {
168178 cancelEvent ( event ) ;
169179
170180 if ( this . state . isHover ) {
171181 this . setState ( { isHover : false } ) ;
172182 }
173- }
183+ } ;
174184
175- onDrop ( event : React . DragEvent < HTMLElement > ) : void {
185+ onDrop = ( event : React . DragEvent < HTMLElement > ) : void => {
176186 cancelEvent ( event ) ;
177187
178188 if ( event . dataTransfer && event . dataTransfer . files ) {
179189 this . processFiles ( event . dataTransfer . files , event . dataTransfer . items ) ;
180190 this . setState ( { isHover : false } ) ;
181191 }
182- }
192+ } ;
183193
184- onRemove ( ) : void {
194+ onRemove = ( ) : void => {
185195 // A value of null is supported by server APIs to clear/remove a file field's value.
186196 this . setFormValue ( null ) ;
187- }
197+ } ;
188198
189199 render ( ) {
190200 const {
@@ -197,31 +207,28 @@ class FileInputImpl extends DisableableInput<FileInputImplProps, State> {
197207 showLabel,
198208 toggleDisabledTooltip,
199209 } = this . props ;
200- const { data, file, isDisabled, isHover } = this . state ;
210+ const { data, error , file, isDisabled, isHover } = this . state ;
201211
202212 const name = this . getInputName ( ) ;
203213 const inputId = `${ name } -fileUpload` ; // Issue 53394: needs to be a distinct input id so it doesn't collide with other elements on the page for this fieldKey
204214 let body ;
205215
206- if ( file ) {
207- const attachedFileClass = classNames ( 'attached-file__inline-container' , {
208- 'file-upload__is-hover' : isHover ,
209- } ) ;
216+ if ( file || typeof data === 'string' ) {
210217 body = (
211218 < div
212- className = { attachedFileClass }
219+ className = { classNames ( 'attached-file__inline-container' , { 'file-upload__is-hover' : isHover } ) }
213220 onDragEnter = { this . onDrag }
214221 onDragLeave = { this . onDragLeave }
215222 onDragOver = { this . onDrag }
216223 onDrop = { this . onDrop }
217224 >
218225 < span className = "fa fa-times-circle attached-file__remove-icon" onClick = { this . onRemove } />
219226 < span className = "fa fa-file-text attached-file--icon" />
220- < span > { file . name } </ span >
221- < div className = "file-upload__error-message" > { this . state . error } </ div >
227+ < span > { file ? file . name : ( data as string ) } </ span >
228+ < div className = "file-upload__error-message" > { error } </ div >
222229 </ div >
223230 ) ;
224- } else if ( data ? .get ( 'value' ) ) {
231+ } else if ( Map . isMap ( data ) && data . get ( 'value' ) ) {
225232 body = (
226233 < FileColumnRenderer
227234 data = { data }
@@ -234,7 +241,7 @@ class FileInputImpl extends DisableableInput<FileInputImplProps, State> {
234241 < >
235242 < input
236243 className = "file-upload__input" // This class makes the file input hidden
237- disabled = { this . state . isDisabled }
244+ disabled = { isDisabled }
238245 id = { inputId }
239246 multiple = { false }
240247 name = { name }
@@ -258,7 +265,7 @@ class FileInputImpl extends DisableableInput<FileInputImplProps, State> {
258265 < i aria-hidden = "true" className = "fa fa-cloud-upload" />
259266
260267 < span > Select file or drag and drop here.</ span >
261- < div className = "file-upload__error-message" > { this . state . error } </ div >
268+ < div className = "file-upload__error-message" > { error } </ div >
262269 </ label >
263270 </ >
264271 ) ;
0 commit comments