def create @user = User.new(params[:user]) respond_to do |format| if @user.save format.html { ... } format.js else format.html { ... } format.js end end end
// app/views/users/create.js.erb
const users = document.querySelector("#users");
users.insertAdjacentHTML("beforeend", "<%= j render(@user) %>");
<ul id="users">
<%= render @users %>
</ul>
<%= form_with model: @user do |form| %>
<%= form.label :name %><br>
<%= form.text_field :name %>
<%= form.submit %>
<% end %>
It was awesome but...
$ rails new my-awesome-project --api
Rails partials
<%# app/views/todos/index.html.erb %>
<h1>Todos</h1>
<%= render "search_form" %>
<%= render @todos %>
<%# app/views/todos/_todo.html.erb %>
<p><%= todo.description %></p>
<%# app/views/todos/show.html.erb %>
<h1>My awesome todo</h1>
<turbo-frame id="<%= dom_id(@todo) %>">
<h2><%= @todo.name %></h2>
<p><%= @todo.description %></p>
<%= link_to 'Edit this todo', edit_todo_path(@todo) %>
</turbo-frame>
<%# app/views/todos/edit.html.erb %>
<h1>Editing message</h1>
<turbo-frame id="<%= dom_id(@todo) %>">
<%# form_with ... %>
</turbo-frame>
What if you need to update multiple frames at once
Or update frames from HTTP responses?
def create user = User.create!(params[:user]) respond_to do |format| format.turbo_stream do render turbo_stream: turbo_stream.append(:users, partial: "users/user", locals: { user: user }) end format.html { redirect_to users_url } end end
format.turbo_stream do render turbo_stream: [ turbo_stream.append(...), turbo_stream.replace(...) ] end
<%# app/views/todos/show.html.erb %>
<%= turbo_stream_from @todo %>
<div id="<%= dom_id(@todo) %>">
<h1><%= @todo.name %></h1>
</div>
class Todo < ApplicationRecord # broadcasts after_create_commit -> { broadcast_append_to self } after_destroy_commit -> { broadcast_remove_to self } after_update_commit -> { broadcast_replace_to self } end