-
Notifications
You must be signed in to change notification settings - Fork 433
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
Turbo frames conditional rendering #378
Comments
Hi @james-reading , this might be a duplicate of this one #257 ? |
@acetinick Hmm I think it might be slightly different. I am not talking about conditionally setting the response turbo frame. I mean conditionally rendering different HTML based on the request turbo frame. What I'd like to do is something like
This works pretty well, but I also need to have the same case statement in the Something like this seems like it would be a double win because not only does it mean I can render different HTML based on the requesting frame, but the server also doesn't have to spend time rendering HTML that ultimately won't be rendered in the browser. |
Are you suggesting adding a turbo-frame mime type?: respond_to do |format|
format.turbo_frame
format.html
end In your scenario I prefer to use the same HTML (perhaps with CSS), but show/hide elements <% if turbo_frame_request? %>
<a href="#" title="Close">X</a>
<% end %> I'm not as worried about some of the extra HTML it might include. If you want to get to that level, you can still use: class PostsController < ApplicationController
def new
@post = Post.new
if turbo_frame_request?
render partial: 'posts/modal_body'
else
render :new
end
end
def create
respond_to do |format|
format.turbo_stream
format.html { redirect_to ... }
end
end
end |
Since turbo_frame response is really an HTML mime-type, adding a custom mime type just for turbo-frames wouldn't be a good solution (although, I guess you could make that same argument for turbo-streams being html). You could implement an html variant (search for variants in ActionController::MimeResponds): Example: class ApplicationController < ActionController::Base
private
def turbo_frame_request_variant
request.variant = :turbo_frame if turbo_frame_request?
end
end
class PostsController < ApplicationController
before_action :turbo_frame_request_variant, only: %i[new create]
def new
@post = Post.new
respond_to do |format|
format.html do |variant|
variant.turbo_frame # renders app/views/posts/new.html+turbo_frame.erb
variant.none # renders app/views/posts/new.html.erb
end
end
end
def create
respond_to do |format|
format.turbo_stream do |variant|
variant.turbo_frame { redirect_to ... }
variant.none { redirect_to ... }
end
format.html { redirect_to ... }
end
end
end |
Thanks @tleish, variants work brilliants actually. It works without the boilerplate Is there any harm to putting |
I suggested this as a default in the turbo-rails gem |
The problem --- The rendering process during a page-wide navigation is opaque, and cannot be extended. Proposals have been made to use third-party rendering tools like [morphdom][], or other animation libraries. Outside of the HTML manipulation, Turbo is also responsible for loading script, transposing permanent elements, etc. How might these tools integrate with Turbo in a way that's compliant with permanent elements. The solution --- When publishing a `turbo:before-render` event, dispatch it with a `render()` function property in addition to the `resume()`. This way, consumer applications can override rendering: ```html import morphdom from "morphdom" addEventListener("turbo:before-render", ({ detail }) => { detail.render = (currentElement, newElement) => { morphdom(currentElement, newElement) } // or, more tersely detail.render = morphdom }) ``` Potentially Closes [hotwired#197][] Potentially Closes [hotwired#378][] Potentially Closes [hotwired#218][] [morphdom]: https://github.com/patrick-steele-idem/morphdom [hotwired#218]: hotwired#218 [hotwired#378]: hotwired#378 [hotwired#197]: hotwired#197
The problem --- The rendering process during a page-wide navigation is opaque, and cannot be extended. Proposals have been made to use third-party rendering tools like [morphdom][], or other animation libraries. Outside of the HTML manipulation, Turbo is also responsible for loading script, transposing permanent elements, etc. How might these tools integrate with Turbo in a way that's compliant with permanent elements. The solution --- When publishing a `turbo:before-render` event, dispatch it with a `render()` function property in addition to the `resume()`. This way, consumer applications can override rendering: ```html import morphdom from "morphdom" addEventListener("turbo:before-render", ({ detail }) => { detail.render = (currentElement, newElement) => { morphdom(currentElement, newElement) } // or, more tersely detail.render = morphdom }) ``` Potentially Closes [hotwired#197][] Potentially Closes [hotwired#378][] Potentially Closes [hotwired#218][] [morphdom]: https://github.com/patrick-steele-idem/morphdom [hotwired#218]: hotwired#218 [hotwired#378]: hotwired#378 [hotwired#197]: hotwired#197
The problem --- The rendering process during a page-wide navigation is opaque, and cannot be extended. Proposals have been made to use third-party rendering tools like [morphdom][], or other animation libraries. Outside of the HTML manipulation, Turbo is also responsible for loading script, transposing permanent elements, etc. How might these tools integrate with Turbo in a way that's compliant with permanent elements. The solution --- When publishing a `turbo:before-render` event, dispatch it with a `render()` function property in addition to the `resume()`. This way, consumer applications can override rendering: ```html import morphdom from "morphdom" addEventListener("turbo:before-render", ({ detail }) => { detail.render = (currentElement, newElement) => { morphdom(currentElement, newElement) } // or, more tersely detail.render = morphdom }) ``` Potentially Closes [hotwired#197][] Potentially Closes [hotwired#378][] Potentially Closes [hotwired#218][] [morphdom]: https://github.com/patrick-steele-idem/morphdom [hotwired#218]: hotwired#218 [hotwired#378]: hotwired#378 [hotwired#197]: hotwired#197
The problem --- The rendering process during a page-wide navigation is opaque, and cannot be extended. Proposals have been made to use third-party rendering tools like [morphdom][], or other animation libraries. Outside of the HTML manipulation, Turbo is also responsible for loading script, transposing permanent elements, etc. How might these tools integrate with Turbo in a way that's compliant with permanent elements. The solution --- When publishing a `turbo:before-render` event, dispatch it with a `render()` function property in addition to the `resume()`. This way, consumer applications can override rendering: ```html import morphdom from "morphdom" addEventListener("turbo:before-render", ({ detail }) => { detail.render = (currentElement, newElement) => { morphdom(currentElement, newElement) } // or, more tersely detail.render = morphdom }) ``` Potentially Closes [hotwired#197][] Potentially Closes [hotwired#378][] Potentially Closes [hotwired#218][] [morphdom]: https://github.com/patrick-steele-idem/morphdom [hotwired#218]: hotwired#218 [hotwired#378]: hotwired#378 [hotwired#197]: hotwired#197
The problem --- The rendering process during a page-wide navigation is opaque, and cannot be extended. Proposals have been made to use third-party rendering tools like [morphdom][], or other animation libraries. Outside of the HTML manipulation, Turbo is also responsible for loading script, transposing permanent elements, etc. How might these tools integrate with Turbo in a way that's compliant with permanent elements. The solution --- When publishing a `turbo:before-render` event, dispatch it with a `render()` function property in addition to the `resume()`. This way, consumer applications can override rendering: ```html import morphdom from "morphdom" addEventListener("turbo:before-render", ({ detail }) => { detail.render = (currentElement, newElement) => { morphdom(currentElement, newElement) } // or, more tersely detail.render = morphdom }) ``` Potentially Closes [hotwired#197][] Potentially Closes [hotwired#378][] Potentially Closes [hotwired#218][] [morphdom]: https://github.com/patrick-steele-idem/morphdom [hotwired#218]: hotwired#218 [hotwired#378]: hotwired#378 [hotwired#197]: hotwired#197
The problem --- The rendering process during a page-wide navigation is opaque, and cannot be extended. Proposals have been made to use third-party rendering tools like [morphdom][], or other animation libraries. Outside of the HTML manipulation, Turbo is also responsible for loading script, transposing permanent elements, etc. How might these tools integrate with Turbo in a way that's compliant with permanent elements. The solution --- When publishing a `turbo:before-render` event, dispatch it with a `render()` function property in addition to the `resume()`. This way, consumer applications can override rendering: ```html import morphdom from "morphdom" addEventListener("turbo:before-render", ({ detail }) => { detail.render = (currentElement, newElement) => { morphdom(currentElement, newElement) } // or, more tersely detail.render = morphdom }) ``` Potentially Closes [hotwired#197][] Potentially Closes [hotwired#378][] Potentially Closes [hotwired#218][] [morphdom]: https://github.com/patrick-steele-idem/morphdom [hotwired#218]: hotwired#218 [hotwired#378]: hotwired#378 [hotwired#197]: hotwired#197
The problem --- The rendering process during a page-wide navigation is opaque, and cannot be extended. Proposals have been made to use third-party rendering tools like [morphdom][], or other animation libraries. Outside of the HTML manipulation, Turbo is also responsible for loading script, transposing permanent elements, etc. How might these tools integrate with Turbo in a way that's compliant with permanent elements. The solution --- When publishing a `turbo:before-render` event, dispatch it with a `render()` function property in addition to the `resume()`. This way, consumer applications can override rendering: ```html import morphdom from "morphdom" addEventListener("turbo:before-render", ({ detail }) => { detail.render = (currentElement, newElement) => { morphdom(currentElement, newElement) } // or, more tersely detail.render = morphdom }) ``` Potentially Closes [hotwired#197][] Potentially Closes [hotwired#378][] Potentially Closes [hotwired#218][] [morphdom]: https://github.com/patrick-steele-idem/morphdom [hotwired#218]: hotwired#218 [hotwired#378]: hotwired#378 [hotwired#197]: hotwired#197
The problem --- The rendering process during a page-wide navigation is opaque, and cannot be extended. Proposals have been made to use third-party rendering tools like [morphdom][], or other animation libraries. Outside of the HTML manipulation, Turbo is also responsible for loading script, transposing permanent elements, etc. How might these tools integrate with Turbo in a way that's compliant with permanent elements. The solution --- When publishing a `turbo:before-render` event, dispatch it with a `render()` function property in addition to the `resume()`. This way, consumer applications can override rendering: ```html import morphdom from "morphdom" addEventListener("turbo:before-render", ({ detail }) => { detail.render = (currentElement, newElement) => { morphdom(currentElement, newElement) } // or, more tersely detail.render = morphdom }) ``` Potentially Closes [hotwired#197][] Potentially Closes [hotwired#378][] Potentially Closes [hotwired#218][] [morphdom]: https://github.com/patrick-steele-idem/morphdom [hotwired#218]: hotwired#218 [hotwired#378]: hotwired#378 [hotwired#197]: hotwired#197
I want to stick a form in a modal, using a link that will request the
new
action to render the form HTML which then gets injected into the modal and opened.This is a pretty common pattern that I've implemented many times before with Rails UJS.
I am now trying to do the same thing with Turbo.
So I have a pre-rendered empty modal with
turbo_frame_tag
in the modal body. When I click the link, the controller renders thenew
template which has the form wrapped in a matchingturbo_frame_tag
. The form gets injected into the modal and I have a stimulus controller which opens the modal onturbo:frame-render
.This works pretty well, but there seems to be a pretty big limitation - The form HTML has to be identical for both the modal, and for when I visit the new URL directly. For example, if I need a close button when in a modal, but a cancel link when visiting the page directly, this doesn't seem possible to handle server-side.
With Rails UJS, My
new
controller action could respond toformat.js
for the modal andformat.html
when visiting directly, making it possible to render different HTML. Asnew
action is a GET, this rules outformat.turbo_stream
which is for non-GET requests only.The text was updated successfully, but these errors were encountered: