-
Notifications
You must be signed in to change notification settings - Fork 436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce turbo:before-permanent-element-render
#622
base: main
Are you sure you want to change the base?
Introduce turbo:before-permanent-element-render
#622
Conversation
129eaa3
to
829fbe0
Compare
Wouldn't you be able to get the same done using |
I considered a permanent-specific event to separate the idea from the details of the rendering (was it a full Drive visit? a Frame navigation? a Stream?) so that the code could be more general purpose. Currently, the I'm also not sure if Turbo Stream rendering currently accounts for permanent elements correctly. If they do, that would be another point in time and event ( If a new event specific to permanent elements isn't warranted, then a |
I've just tried this out, and it appears that Turbo Stream operations ignore You can experiment with the code on JSFiddle: <html>
<head>
<script type="importmap">
{
"imports": {
"@hotwired/turbo": "https://cdn.skypack.dev/@hotwired/turbo"
}
}
</script>
<script type="module">
import "@hotwired/turbo"
addEventListener("click", ({ target }) => {
if (target.matches("button")) {
const { content } = target.querySelector("template")
target.append(content.cloneNode(true))
}
})
</script>
<script type="module" src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
</head>
<body>
<p id="permanent" data-turbo-permanent>This should not change when you click the button</p>
<button type="button">
Click me, and hopefully nothing changes
<template>
<turbo-stream action="replace" target="permanent">
<template><p id="permanent" data-turbo-permanent>Uh oh, this changed when you clicked the button!</p></template>
</turbo-stream>
</template>
</button>
</body>
</html> My gut tells me that's surprising behavior, but maybe it isn't. I've opened #623 to discuss this further. Turbo Streams aside, the gap between |
8e412f1
to
ebabd5f
Compare
ebabd5f
to
c037d3e
Compare
Does this mean that we get the chance to rid the menu "flashing" when navigating with turbo drive? |
Maybe! Could you share some more details of what you're experiencing? |
Sure. The "flashing" effect I'm talking about usually happens when clicking around a menu or top nav. When a user clicks any of the menu options, Turbo Drive replaces the entire body. The side-effect is that since the "nav" partial is part of the layout which is part of the body, it gets replaced too. This is totally expected cause the "active" menu link has to somehow be updated. However is it suboptimal cause the user sees a "flash" as a result of the "rerender". At the moment one could set the entire menu as I'm also attaching a couple of videos below further demonstrating the issue: gone_fishing.mp4Video source: Gone fishing tutorial app railsdevs.mp4Video source: RailsDevs |
cc @seanpdoyle |
8444071
to
316929f
Compare
316929f
to
dbef5c4
Compare
dbef5c4
to
a8924f4
Compare
5bab75b
to
2d30dc2
Compare
2d30dc2
to
7ef02be
Compare
7ef02be
to
b51399a
Compare
c82aa26
to
a7b66e5
Compare
While transposing a [permanent element][] from page to page, dispatch a `turbo:before-permanent-element-render` event on the document with a `(currentPermanentElement: Element, newPermanentElement: Element) => void` available as the event's `detail.render` property. The `turbo:before-permanent-element-render` is named to follow the pattern established by its predecessors (`turbo:before-render`, `turbo:before-frame-render`, `turbo:before-stream-render`), and its `CustomEvent.detail.render` property name mirrors the `turbo:before-render` event's `CustomEvent.detail.render` property. This opportunity to modify a permanent element might be useful if it's possible for the preserved element to become partially stale. For example, consider an invalid `<form>` submission with an `<input type="file">`. Since the server's response cannot fully encode the submitted file into the response's element, it might be a useful to mark it with `[data-turbo-permanent]` to preserve whatever client-side state precedes the submission: ```html <label for="profile_image">Profile image</label> <input id="profile_image" type="file" data-turbo-permanent> ``` Suppose the uploaded file is too large, or doesn't match the server's expectations for file type. The server's response might contain a fragment like: ```html <label for="profile_image">Profile image</label> <input id="profile_image" type="file" data-turbo-permanent class="invalid" aria-describedby="profile_image_error"> <p id="profile_image_error">Profile image is too large (5GB). Try a smaller file (<5KB)</p> ``` Prior to this change, the fact that the `<input>` is marked with `[data-turbo-permanent]` would ignore the `[class]` and `[aria-describedby]` attributes from the response, and the `<input>` would remain unchanged (with the attached file still in-memory). With a new `turbo:before-permanent-element-render` available, there's an opportunity to do application-specific merging: ```js addEventListener("turbo:before-permanent-element-render", ({ target, { detail } }) => { detail.render = (currentElement, newElement) => { currentElement.setAttribute("class", newElement.getAttribute("class")) currentElement.setAttribute("aria-describedby", newElement.getAttribute("aria-describedby")) } }) ``` [permanent element]: https://turbo.hotwired.dev/handbook/building#persisting-elements-across-page-loads
a7b66e5
to
a188c94
Compare
While transposing a permanent element from page to page, dispatch a
turbo:before-permanent-element-render
event on the document with a(currentPermanentElement: Element, newPermanentElement: Element) => void
available as the event'sdetail.render
property.The
turbo:before-permanent-element-render
is named to follow thepattern established by its predecessors (
turbo:before-render
,turbo:before-frame-render
,turbo:before-stream-render
), and itsCustomEvent.detail.render
property name mirrors theturbo:before-render
event'sCustomEvent.detail.render
property.This opportunity to modify a permanent element might be useful if it's
possible for the preserved element to become partially stale. For
example, consider an invalid
<form>
submission with an<input type="file">
.Since the server's response cannot fully encode the submitted file into
the response's element, it might be a useful to mark it with
[data-turbo-permanent]
to preserve whatever client-side state precedesthe submission:
Suppose the uploaded file is too large, or doesn't match the server's
expectations for file type. The server's response might contain
a fragment like:
Prior to this change, the fact that the
<input>
is marked with[data-turbo-permanent]
would ignore the[class]
and[aria-describedby]
attributes from the response, and the<input>
would remain unchanged (with the attached file still in-memory).
With a new
turbo:before-permanent-element-render
available, there's anopportunity to do application-specific merging: