-
Notifications
You must be signed in to change notification settings - Fork 430
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
Render 4xx responses within frame #210
base: main
Are you sure you want to change the base?
Conversation
42a5e6f
to
855b461
Compare
.find(target => target) | ||
|
||
if (response.redirected && target == "_top") { | ||
navigator.formSubmission = formSubmission |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sstephenson this felt like the shortest distance to achieve the outcome. The awkwardness signals to me that there is a missing concept or delegate here.
A means of delegating or directly accessing the Navigator would also enable the transformation of a frame navigation to a fully formed Visit
to drive the page.
Hey @seanpdoyle 👋🏻 Thanks for putting this together, first of all! I'm running into some similar issues with Turbo Frames and responses/navigations so wanted to get your thoughts. The way I'm thinking about it, I'm seeing two main options:
or
Side-effects wise, the former means that any time the server responds with a 422/5xx to a request coming from within a frame that's targeting I'm not sure I've got a strong opinion on either direction, but could you speak to the strategy behind choosing one or the other for the implementation of this feature? I wonder if the real drawback here is the simple binary nature of Tagging these because they feel relevant: #138, Hotwire Discourse #1562 |
@jon-sully my intuition pushes me toward the first option you laid out. It's also least disruptive in terms of existing Turbo conventions and patterns. In my experiences, there certainly is a need for some version of the second option you mentioned, with regard to an ability to "break out" of a frame and combine the scoped HTML modifications and DOM state preservation of a Turbo Frame with the URL push state changes of a Turbo Visit. We still haven't thread that needle yet, in terms of an attribute-based "interface", but there has been some exploration (#167). |
Cool! Thanks for the thoughts. Like I said, I don't think I have a strong opinion here; either way accomplishes the goal of my forms working inside a frame when they fail and when they don't... and this PR does that from what I can tell! Hopefully this gets some traction in the coming weeks 💯 |
38adf74
to
719b24e
Compare
I'd like to be able to allow certain pages to respond with html that forces "top" in the response. For example, if a users session times out and they click on a form (or link) within a frame which does not have target="_top", the response redirects the user to the login page, but to the user nothing happens on the page. If the response returned data which told Turbo to load at the top, this would be useful in this scenario. |
Where are we on this ? I had yet another case where this was an issue today. I work around it by using Turbo streams to update my entire page or use javascript to force a refresh, but both are, at best, temporary workarounds. |
@Growiel probably not what you intended, but asking for status suggests this issue is being neglected and asks a maintainer to give it their attention. The project is in beta, so some issues like this are expected. If you look at PR and commit activity on https://github.com/hotwired projects, you'll see quite a bit of momentum from contributors, especially Basecamp and Thoughtbot folks. This issue doesn't need extra attention. Like you, I share some concerns around this issue. I don't have bandwidth right now to either help solve it for everyone or to dig in to work around it for myself, so I've subscribed for GitHub updates and I choose not to deploy to this production yet. This is open source. While Basecamp made Turbo happen (with the community and standing on Turbolinks shoulders), we all have some responsibility for helping it along. I've seen several small PRs merged in from folks new to Turbo, fixing some simple errors they ran into. ✌️ ❤️ |
Fantastic answer, @ansonhoyt 👏🏻 As with all things OSS, if the issue is pressing enough to an individual, we are all capable of forking the project, fixing it in our fork, and running that code wherever we need it to. Otherwise open-source is a contribution-based process we should all take part in and have good expectations around And I'm also not assuming intent on any prior comment's tone, just speaking in a general sense! |
I get both of your points but I can't really contribute mote in this specific case: the PR is already there and working, the only thing I can do is make sure it isn't forgotten. Not because the project is inactive, like @ansonhoyt seems to think I meant, but because there's so much going on, it's easy for one to slip through the cracks. Before investing the time to do what @jon-sully suggested, it's better to know if the official fix will be released or not. Why ? Because based on other PRs like this one: #56 sometimes while the use case is relevant (at least 3 tickets and 2 questions on the discussions site exist), the maintainers have decided that this specific case will not be supported. So before I invest in a custom fork, I'd rather ask if I can hope to see official support one day. Hope it makes sense. |
@Growiel I'm just suggesting you look at the issue (in)activity in context of the project activity. I'd probably ask for status too if I see an RC release come out without this being addressed. That'd be a good signal this might be forgotten. No worries though, I know it's easy to misread someone's comment. Sorry that I misread yours. I'm just another guy excited to get this working too. 😄 |
Hey @seanpdoyle what lead to this one getting closed? 👀 |
ec8126b
to
9b82e49
Compare
5d0fc51
to
720cf7f
Compare
@seanpdoyle What do you think about rendering 4xx responses within the frame, but replacing the whole page for 5xx responses? 5xx responses are usually designed for the whole page, and they won't fit small frames. |
6931b98
to
03d26fd
Compare
@mrhead I think that's a reasonable expectation. Since Frame requests with a |
I think the logic should be simpler. If the turbo-frame response does not include the expected turbo-frame id, replace the whole page and update the URL, regardless if the response is a 2xx, 3xx, 4xx or 5xx. This solves multiple success or error cases when you want the response to turbo-frame to replace the whole page. |
@tleish I think that's also a reasonable behavior to explore. If I'm understanding your proposal correctly, that feels outside the scope of this proposal. This PR is scoped to handling |
03d26fd
to
ce7d5e8
Compare
@seanpdoyle should this not also be the case for normal GET requests? If a |
The use case --- Consider submitting a `<form data-turbo-frame="_top">` from within a `<turbo-frame>`: ```html <dialog open> <turbo-frame id="dialog"> <form data-turbo-frame="_top" method="POST" action="/posts"> <!-- ... --> </form> </turbo-frame> </dialog> ``` In the case of success, the response will be a [303 redirecting to another URL][303]. In the case of a failed submission, the response will be a [422 with an HTML body][]: ```ruby class PostsController < ApplicationController def create @post = Post.create!(post_params) redirect_to post_url(@post) rescue ActiveRecord::RecordNotSaved render inline: <<~HTML, status: :unprocessable_entity <turbo-frame id="dialog"> <form data-turbo-frame="_top" method="POST" action="/posts"> <!-- ... --> </form> </turbo-frame> HTML end end ``` [303]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303 [422]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422 The current behavior --- Since the `<form>` element declares its target as `_top`, a successful submission resulting in the [303][] response, the entire page redirect. Similarly, in the case of an invalid submission, _the entire page's HTML_ will be replaced by the response, in spite of the submission occurring within a `<turbo-frame>` element. The desired outcome --- A valid submission behaves as expected and desired: redirect the `_top` (entire page) to the URL. In the case of a submission without Turbo, a failed submission would result in a full re-render of the page, keeping the `<dialog>` containing the form open. Any information or context in the "background" would be re-rendered, but would exist. With the introduction of Turbo Frames to the situation as a progressive enhancement, a developer might expect the server's response to be limited to only replacing the contents of the `<turbo-frame>` after a failure. Proposed change --- The current implementation treats submissions from within a `<turbo-frame target="_top">` different than it treats elements declared without a `[data-turbo-frame]` attribute or with `[data-turbo-frame]` referring to another that refers to another `<turbo-frame>` element on the page. To account for the proposed change in behavior, this commit changes the `FrameController` and `FrameRedirector` to handle _all_ frame submissions. If a Frame or form within a frame targets `_top`, that redirect would only occur after a successful redirect response.
ce7d5e8
to
a16f650
Compare
what’s the stopper here? this missing behavior is what keeps me from using turbo and others even (wrongfully) assume this behavior, see e.g. hotwired/turbo-rails#122. |
Appreciate all your work. Just wondering if this is still up for consideration or if perhaps a different approach is being considered. ❤️ |
I can't speak for @seanpdoyle but I believe this draft PR represents an idea that can accommodate several different functionalities, but there are a handful of other draft and/or open PRs aiming to accommodate other functionalities that may be the same. E.g. there are a lot of ideas floating around in the "make frames more flexible" space at the moment, and none has been settled on yet by the core team(s). Thus, this PR is still just an idea for consideration as it pertains to the overall Turbo API and expectations, less so a fully-featured implementation ready-for-merge. |
The use case
Consider submitting a
<form data-turbo-frame="_top">
from within a<turbo-frame>
:In the case of success, the response will be a 303 redirecting to
another URL.
In the case of a failed submission, the response will be a 422 with an
HTML body:
The current behavior
Since the
<form>
element declares its target as_top
, a successfulsubmission resulting in the 303 response, the entire page redirect.
Similarly, in the case of an invalid submission, the entire page's
HTML will be replaced by the response, in spite of the submission
occurring within a
<turbo-frame>
element.The desired outcome
A valid submission behaves as expected and desired: redirect the
_top
(entire page) to the URL.
In the case of a submission without Turbo, a failed submission would
result in a full re-render of the page, keeping the
<dialog>
containing the form open. Any information or context in the "background"
would be re-rendered, but would exist.
With the introduction of Turbo Frames to the situation as a progressive
enhancement, a developer might expect the server's response to be
limited to only replacing the contents of the
<turbo-frame>
after afailure.
Proposed change
The current implementation treats submissions from within a
<turbo-frame target="_top">
different than it treats elements declaredwithout a
[data-turbo-frame]
attribute or with[data-turbo-frame]
referring to another that refers to another
<turbo-frame>
element onthe page.
To account for the proposed change in behavior,
this commit changes the
FrameController
andFrameRedirector
tohandle all frame submissions. If a Frame or form within a frame
targets
_top
, that redirect would only occur after a successfulredirect response.