简体   繁体   中英

respond_to do |format| format.js not working (ruby on rails & ajax)

I'm trying to use ajax for displaying searching results in a Ruby on rails app. However, after I submit the search form, it shows ActionController::UnknownFormat error at the line where it says respond_to respond_to do |format|. It does not allow me render partial and I'm not sure why. Using Rails 6.0.2.2

availabilities/_searchform.html.erb

<form>
    <%= simple_form_for(:search, :url => search_rides_path, :remote => true, :method => :get) do |f| %>
        <div class="form-row">
            <div class="form-group col-md-2">
                <%= f.input :start_city, label: 'Start City', class: "form-control", error: 'Start address is mandatory, please specify one' %>
            </div>
            <div class="form-group col-md-4">
                <%= f.input :start_street_address, label: 'Start Street Address', class: "form-control" %>
            </div>
        </div>
        <div class="form-row">
            <div class="form-group col-md-2">
                <%= f.input :end_city, label: 'Destination City', class: "form-control" %>
            </div>
            <div class="form-group col-md-4">
                <%= f.input :end_street_address, label: 'Destionation Street Address', class: "form-control" %>
            </div>
        </div>
        <div class="form-row">
            <div class="form-group col-md-2">
                <%= f.input :trip_date, as: :date, html5: true, inline_label: 'Yes, remember me', class: "form-control" %>
            </div>
            <div class="form-group col-md-2">
                <%= f.input :trip_time, as: :time, html5: true, inline_label: 'Yes, remember me', class: "form-control" %>
            </div>
            <div class="form-group col-md-2">
                <%= f.input :lowest_acceptable_price, label: 'Expected Price', class: "form-control" %>
            </div>
        </div>
            <%= f.submit "Search", class: "btn btn-primary" %>
    <% end %>
</form>

part of avilabilities_controller.rb

class AvailabilitiesController < ApplicationController
  before_action :set_availability, only: [:show, :edit, :update, :destroy]
  # respond_to :html, :json, :js
  # GET /availabilities
  # GET /availabilities.json
  def index
    @availabilities = Availability.unmatched
  end

  def search
    if params[:search]
      @availabilities = Availability.unmatched.search(params[:search])
      if @availabilities
        respond_to do |format|
          format.js { render partial: 'availabilities/result.html'}
        end
      else
        respond_to do |format|
          flash.now[:alert] = "Could not find an availability"
          format.js { render partial: 'availabilities/result.html'}
        end
      end
    else
      @availabilities = Availability.unmatched
    end
  end
end

availabilities/search.html.erb

<p id="notice"><%= notice %></p>
<%= render 'searchform' %>
<div id="results">
</div>

availabilities/_result.html.erb

<% if @availabilities %>
    <%@availabilities.each do |availability|%>
          <div class="card" style="width: 18rem;">
            <div class="card-body">
                <h5 class="card-title">Ride</h5>
                <strong>Start city: </strong> <%= availability.start_city %><br>
                <strong>Start street address: </strong><%= availability.start_street_address %><br>
                <strong>End city: </strong><%= availability.end_city %><br>
                <strong>End street address: </strong><%= availability.end_street_address %><br>
                <strong>Trip Time: </strong><%= availability.trip_time %><br>
                <strong>Price Requested: </strong><%= availability.lowest_acceptable_price %><br>
                <br>
                <a href="#" class="btn btn-primary">View Details</a>
                <a href="#" class="btn btn-primary">Request Ride</a>
            </div>
        </div>
    <% end %>
  </div>
<% else %>
    <h1> No results have been found </h1>
<% end %>

availabilities/_result.js.erb

alert("hello world!")

You have fundamentally misunderstood how Rails UJS works. When you use remote: true Rails UJS sends an XHR request to Rails with a application/javascript content type. Rails renders some JavaScript (or what should have been js) and then sends it back to the client.

Rails UJS takes the response and essentially pops it into a script tag to eval it. If the response is a bunch of HTML this will just cause a parser error.

What you want to do is:

class AvailabilitiesController < ApplicationController
  before_action :set_availability, only: [:show, :edit, :update, :destroy]
  # respond_to :html, :json, :js
  # GET /availabilities
  # GET /availabilities.json
  def index
    @availabilities = Availability.unmatched
  end

  def search
    if params[:search]
      @availabilities = Availability.unmatched.search(params[:search])
      respond_to do |format|
        flash.now[:alert] = "Could not find an availability" unless @availabilities.any?
        format.js { render :result  }
      end
    else
      @availabilities = Availability.unmatched
    end
  end
end

Then create a js.erb view containing JavaScript that alters the existing DOM:

// app/views/availabilites/results.js.erb
document.getElementById("results")
        .innerHTML = "<%= j render(partial: 'results.html.erb') %>";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM