Remote form with Rails
  • Views

  • Wrap your form in a div with a known id. You'll use this as your hx-target when the form is submitted.

  • <div id="task-form">
      <%= render partial: "partials/task_form" %>
    </div>
  • Write your form as normal, but use hx-post instead of action, and specify a hx-target

  • # /views/partials/_task_form.html.erb
    
    <div class="flex flex-col space-y-3">
      <% if @task.persisted? %>
        <div class="bg-blue-600 text-white p-5 rounded">
          Great! Your details have been saved!
        </div>
      <% else %>
        <%= render partial: "shared/form_errors", locals: { record: @task } %>
        <form hx-post="<%= new_task_path %>" hx-target="#task-form" >
          <div class="grid grid-cols-7 md:space-x-4 space-y-3 md:space-y-0">
            <div class="md:col-span-2 col-span-7">
              <label for="name-field">Name</label>
              <input class="<%= 'invalid' if @task.errors[:name].present? %>" id="name-field" type="text" placeholder="Task Name" name="task[name]" value="<%= @task.name %>" />
            </div>
            <div class="md:col-span-1 col-span-7">
              <label>&nbsp;</label>
              <input type="submit" value="Submit">
            </div>
          </div>
        </form>
      <% end %>
    </div>
  • Controller

  • Add a method to your application controller that looks out for the HX-Request header and responds without the full layout.

  • class ApplicationController < ActionController::Base
    
      def support_partial_response
        if request.headers['HX-Request']
          @async_request = true
          render :layout => false
        else  
          render 
        end
      end
      
    end
  • Now add that method to the final line of whatever controller action you'd like to support

  • class Tasks < ApplicationController
    
      def new
        if request.post?
          @task = Task.new(task_params)
          @task.save
        end
        support_partial_response
      end
      
    end

  • Website Page