1+ import { serialize } from 'object-to-formdata'
12import axios , { AxiosInstance , AxiosRequestConfig , AxiosResponse , AxiosError } from 'axios'
23import Errors from './Errors'
3- import { deepCopy } from './util'
4+ import { deepCopy , hasFiles } from './util'
5+
6+ interface Progress {
7+ total : number
8+ loaded : number
9+ percentage : number
10+ }
411
512class Form {
613 [ key : string ] : any
@@ -21,10 +28,15 @@ class Form {
2128 */
2229 errors : Errors = new Errors ( )
2330
31+ /**
32+ * The upload progress object.
33+ */
34+ progress : Progress | undefined = undefined
35+
2436 static axios : AxiosInstance
2537 static routes : Record < string , string > = { }
2638 static errorMessage = 'Something went wrong. Please try again.'
27- static ignore = [ 'busy' , 'successful' , 'errors' , 'originalData' ]
39+ static ignore = [ 'busy' , 'successful' , 'errors' , 'progress' , ' originalData']
2840
2941 /**
3042 * Create a new form instance.
@@ -81,6 +93,7 @@ class Form {
8193 this . errors . clear ( )
8294 this . busy = true
8395 this . successful = false
96+ this . progress = undefined
8497 }
8598
8699 /**
@@ -89,6 +102,7 @@ class Form {
89102 finishProcessing ( ) {
90103 this . busy = false
91104 this . successful = true
105+ this . progress = undefined
92106 }
93107
94108 /**
@@ -97,6 +111,7 @@ class Form {
97111 clear ( ) {
98112 this . errors . clear ( )
99113 this . successful = false
114+ this . progress = undefined
100115 }
101116
102117 /**
@@ -151,15 +166,27 @@ class Form {
151166 submit ( method : string , url : string , config : AxiosRequestConfig = { } ) : Promise < AxiosResponse > {
152167 this . startProcessing ( )
153168
169+ config = {
170+ data : { } ,
171+ params : { } ,
172+ url : this . route ( url ) ,
173+ method : method as any ,
174+ onUploadProgress : this . handleUploadProgress . bind ( this ) ,
175+ ...config
176+ }
177+
154178 if ( method . toLowerCase ( ) === 'get' ) {
155- config . params = { ...this . data ( ) , ...( config . params || { } ) }
179+ config . params = { ...this . data ( ) , ...config . params }
156180 } else {
157- config . data = { ...this . data ( ) , ...( config . data || { } ) }
181+ config . data = { ...this . data ( ) , ...config . data }
182+
183+ if ( hasFiles ( config . data ) ) {
184+ config . transformRequest = [ data => serialize ( data ) ]
185+ }
158186 }
159187
160188 return new Promise ( ( resolve , reject ) => {
161- // @ts -ignore
162- ( Form . axios || axios ) . request ( { url : this . route ( url ) , method, ...config } )
189+ ( Form . axios || axios ) . request ( config )
163190 . then ( ( response : AxiosResponse ) => {
164191 this . finishProcessing ( )
165192 resolve ( response )
@@ -176,6 +203,7 @@ class Form {
176203 */
177204 handleErrors ( error : AxiosError ) {
178205 this . busy = false
206+ this . progress = undefined
179207
180208 if ( error . response ) {
181209 this . errors . set ( this . extractErrors ( error . response ) )
@@ -201,6 +229,17 @@ class Form {
201229 return { ...response . data }
202230 }
203231
232+ /**
233+ * Handle the upload progress.
234+ */
235+ handleUploadProgress ( event : ProgressEvent ) {
236+ this . progress = {
237+ total : event . total ,
238+ loaded : event . loaded ,
239+ percentage : Math . round ( ( event . loaded * 100 ) / event . total )
240+ }
241+ }
242+
204243 /**
205244 * @deprecated
206245 */
0 commit comments