@@ -20,6 +20,11 @@ export type ComponentHooks = {
2020 connect : ( component : Component ) => MaybePromise ;
2121 disconnect : ( component : Component ) => MaybePromise ;
2222 'request:started' : ( requestConfig : any ) => MaybePromise ;
23+ 'render:started' : (
24+ backendResponseBody : string ,
25+ backendResponse : BackendResponse ,
26+ controls : { shouldRender : boolean }
27+ ) => MaybePromise ;
2328 'render:finished' : ( component : Component ) => MaybePromise ;
2429 'response:error' : ( backendResponse : BackendResponse , controls : { displayError : boolean } ) => MaybePromise ;
2530 'loading.state:started' : ( element : HTMLElement , request : BackendRequest ) => MaybePromise ;
@@ -300,34 +305,43 @@ export default class Component {
300305
301306 this . backendRequest . promise . then ( async ( response ) => {
302307 const backendResponse = new BackendResponse ( response ) ;
303- const html = await backendResponse . getBody ( ) ;
308+ const result = await backendResponse . checkResponseType ( ) ;
304309
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
306322 for ( const input of Object . values ( this . pendingFiles ) ) {
307323 input . value = '' ;
308324 }
309325
326+ const backendResponseBody = result . body ;
327+
310328 // 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' ) {
316330 const controls = { displayError : true } ;
317331 this . valueStore . pushPendingPropsBackToDirty ( ) ;
318332 this . hooks . triggerHook ( 'response:error' , backendResponse , controls ) ;
319333
320- if ( controls . displayError && ! headers . get ( 'Content-Type' ) ?. includes ( 'application/json' ) ) {
321- this . renderError ( html ) ;
334+ if ( controls . displayError ) {
335+ this . renderError ( backendResponseBody ) ;
322336 }
323337
324338 this . backendRequest = null ;
325339 thisPromiseResolve ( backendResponse ) ;
326-
327340 return response ;
328341 }
329342
330- this . processRerender ( html , backendResponse ) ;
343+ // HTML processing
344+ this . processRerender ( backendResponseBody , backendResponse ) ;
331345 const liveUrl = backendResponse . getLiveUrl ( ) ;
332346 if ( liveUrl ) {
333347 history . replaceState (
@@ -337,11 +351,9 @@ export default class Component {
337351 ) ;
338352 }
339353
340- // finally resolve this promise
341354 this . backendRequest = null ;
342355 thisPromiseResolve ( backendResponse ) ;
343356
344- // do we already have another request pending?
345357 if ( this . isRequestPending ) {
346358 this . isRequestPending = false ;
347359 this . performRequest ( ) ;
@@ -351,9 +363,9 @@ export default class Component {
351363 } ) ;
352364 }
353365
354- private processRerender ( html : string , backendResponse : BackendResponse ) {
366+ private processRerender ( backendResponseBody : string , backendResponse : BackendResponse ) {
355367 const controls = { shouldRender : true } ;
356- this . hooks . triggerHook ( 'render:started' , html , backendResponse , controls ) ;
368+ this . hooks . triggerHook ( 'render:started' , backendResponseBody , backendResponse , controls ) ;
357369 // used to notify that the component doesn't live on the page anymore
358370 if ( ! controls . shouldRender ) {
359371 return ;
@@ -387,7 +399,7 @@ export default class Component {
387399
388400 let newElement : HTMLElement ;
389401 try {
390- newElement = htmlToElement ( html ) ;
402+ newElement = htmlToElement ( backendResponseBody ) ;
391403
392404 if ( ! newElement . matches ( '[data-controller~=live]' ) ) {
393405 throw new Error ( 'A live component template must contain a single root controller element.' ) ;
@@ -477,7 +489,7 @@ export default class Component {
477489 }
478490
479491 // inspired by Livewire!
480- private renderError ( html : string ) : void {
492+ private renderError ( backendResponseBody : string ) : void {
481493 let modal = document . getElementById ( 'live-component-error' ) ;
482494 if ( modal ) {
483495 modal . innerHTML = '' ;
@@ -505,7 +517,7 @@ export default class Component {
505517 document . body . style . overflow = 'hidden' ;
506518 if ( iframe . contentWindow ) {
507519 iframe . contentWindow . document . open ( ) ;
508- iframe . contentWindow . document . write ( html ) ;
520+ iframe . contentWindow . document . write ( backendResponseBody ) ;
509521 iframe . contentWindow . document . close ( ) ;
510522 }
511523
0 commit comments