Skip to content

Could turbo-frame elements dispatch turbo events during their navigation lifecycle? #54

@seanpdoyle

Description

@seanpdoyle

As discussed in Are transitions and animations on Hotwire roadmap?, @sstephenson mentions that there would be utility in exposing appropriate seams to consumer applications.

One potential solution could involve dispatching the existing turbo:-prefixed events as a <turbo-frame> element progresses through a navigation. Those events could be dispatched and bubble up from the turbo-frame element, making the frame available as the CustomEvent.target when appropriate. Page-level turbo:-prefixed events would still dispatch off the document element.

In addition to the value it would bring for ancestors to be notified of various lifecycle hooks, it could also enable the cancelation of turbo-frame visitations, and could expose timing metrics as part of frame-scoped turbo:load events.

From a technical perspective, the events could be dispatched from the various empty FrameController hooks:

requestStarted(request: FetchRequest) {
this.element.setAttribute("busy", "")
}
requestPreventedHandlingResponse(request: FetchRequest, response: FetchResponse) {
this.resolveVisitPromise()
}
async requestSucceededWithResponse(request: FetchRequest, response: FetchResponse) {
await this.loadResponse(response)
this.resolveVisitPromise()
}
requestFailedWithResponse(request: FetchRequest, response: FetchResponse) {
console.error(response)
this.resolveVisitPromise()
}
requestErrored(request: FetchRequest, error: Error) {
console.error(error)
this.resolveVisitPromise()
}
requestFinished(request: FetchRequest) {
this.element.removeAttribute("busy")
}
formSubmissionStarted(formSubmission: FormSubmission) {
}
formSubmissionSucceededWithResponse(formSubmission: FormSubmission, response: FetchResponse) {
const frame = this.findFrameElement(formSubmission.formElement)
frame.controller.loadResponse(response)
}
formSubmissionFailedWithResponse(formSubmission: FormSubmission, fetchResponse: FetchResponse) {
}
formSubmissionErrored(formSubmission: FormSubmission, error: Error) {
}
formSubmissionFinished(formSubmission: FormSubmission) {
}

Alternatively, a FrameController could be provided with its own Session instance scoped to the <turbo-frame> element (as opposed to the current implementation which operates on the document.documentElement element).

In theory, there could be a lot of value in unifying the implementations of how a page and a frame navigate, but might involve a larger set of architectural changes. Are there conceptual mismatches between a frame-scoped Session / Navigator pairing and the current implementation which relies on FormInterceptor and LinkInterceptor instances?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions