@@ -20,6 +20,11 @@ export type ComponentHooks = {
20
20
connect : ( component : Component ) => MaybePromise ;
21
21
disconnect : ( component : Component ) => MaybePromise ;
22
22
'request:started' : ( requestConfig : any ) => MaybePromise ;
23
+ 'render:started' : (
24
+ backendResponseBody : string ,
25
+ backendResponse : BackendResponse ,
26
+ controls : { shouldRender : boolean }
27
+ ) => MaybePromise ;
23
28
'render:finished' : ( component : Component ) => MaybePromise ;
24
29
'response:error' : ( backendResponse : BackendResponse , controls : { displayError : boolean } ) => MaybePromise ;
25
30
'loading.state:started' : ( element : HTMLElement , request : BackendRequest ) => MaybePromise ;
@@ -300,34 +305,43 @@ export default class Component {
300
305
301
306
this . backendRequest . promise . then ( async ( response ) => {
302
307
const backendResponse = new BackendResponse ( response ) ;
303
- const html = await backendResponse . getBody ( ) ;
308
+ const result = await backendResponse . checkResponseType ( ) ;
304
309
305
- // clear sent files inputs
310
+ if ( result . type === 'json' ) {
311
+ this . backendRequest = null ;
312
+ thisPromiseResolve ( backendResponse ) ;
313
+
314
+ if ( this . isRequestPending ) {
315
+ this . isRequestPending = false ;
316
+ this . performRequest ( ) ;
317
+ }
318
+ return response ;
319
+ }
320
+
321
+ // Clear all file inputs
306
322
for ( const input of Object . values ( this . pendingFiles ) ) {
307
323
input . value = '' ;
308
324
}
309
325
326
+ const backendResponseBody = result . body ;
327
+
310
328
// if the response does not contain a component, render as an error
311
- const headers = backendResponse . response . headers ;
312
- if (
313
- ! headers . get ( 'Content-Type' ) ?. includes ( 'application/vnd.live-component+html' ) &&
314
- ! headers . get ( 'X-Live-Redirect' )
315
- ) {
329
+ if ( result . type === 'invalid' ) {
316
330
const controls = { displayError : true } ;
317
331
this . valueStore . pushPendingPropsBackToDirty ( ) ;
318
332
this . hooks . triggerHook ( 'response:error' , backendResponse , controls ) ;
319
333
320
- if ( controls . displayError && ! headers . get ( 'Content-Type' ) ?. includes ( 'application/json' ) ) {
321
- this . renderError ( html ) ;
334
+ if ( controls . displayError ) {
335
+ this . renderError ( backendResponseBody ) ;
322
336
}
323
337
324
338
this . backendRequest = null ;
325
339
thisPromiseResolve ( backendResponse ) ;
326
-
327
340
return response ;
328
341
}
329
342
330
- this . processRerender ( html , backendResponse ) ;
343
+ // HTML processing
344
+ this . processRerender ( backendResponseBody , backendResponse ) ;
331
345
const liveUrl = backendResponse . getLiveUrl ( ) ;
332
346
if ( liveUrl ) {
333
347
history . replaceState (
@@ -337,11 +351,9 @@ export default class Component {
337
351
) ;
338
352
}
339
353
340
- // finally resolve this promise
341
354
this . backendRequest = null ;
342
355
thisPromiseResolve ( backendResponse ) ;
343
356
344
- // do we already have another request pending?
345
357
if ( this . isRequestPending ) {
346
358
this . isRequestPending = false ;
347
359
this . performRequest ( ) ;
@@ -351,9 +363,9 @@ export default class Component {
351
363
} ) ;
352
364
}
353
365
354
- private processRerender ( html : string , backendResponse : BackendResponse ) {
366
+ private processRerender ( backendResponseBody : string , backendResponse : BackendResponse ) {
355
367
const controls = { shouldRender : true } ;
356
- this . hooks . triggerHook ( 'render:started' , html , backendResponse , controls ) ;
368
+ this . hooks . triggerHook ( 'render:started' , backendResponseBody , backendResponse , controls ) ;
357
369
// used to notify that the component doesn't live on the page anymore
358
370
if ( ! controls . shouldRender ) {
359
371
return ;
@@ -387,7 +399,7 @@ export default class Component {
387
399
388
400
let newElement : HTMLElement ;
389
401
try {
390
- newElement = htmlToElement ( html ) ;
402
+ newElement = htmlToElement ( backendResponseBody ) ;
391
403
392
404
if ( ! newElement . matches ( '[data-controller~=live]' ) ) {
393
405
throw new Error ( 'A live component template must contain a single root controller element.' ) ;
@@ -477,7 +489,7 @@ export default class Component {
477
489
}
478
490
479
491
// inspired by Livewire!
480
- private renderError ( html : string ) : void {
492
+ private renderError ( backendResponseBody : string ) : void {
481
493
let modal = document . getElementById ( 'live-component-error' ) ;
482
494
if ( modal ) {
483
495
modal . innerHTML = '' ;
@@ -505,7 +517,7 @@ export default class Component {
505
517
document . body . style . overflow = 'hidden' ;
506
518
if ( iframe . contentWindow ) {
507
519
iframe . contentWindow . document . open ( ) ;
508
- iframe . contentWindow . document . write ( html ) ;
520
+ iframe . contentWindow . document . write ( backendResponseBody ) ;
509
521
iframe . contentWindow . document . close ( ) ;
510
522
}
511
523
0 commit comments