1

I have a mini-update method in my model that only updates one field, set up in a chart (so I see the form for each row). It works properly, but want it to update using AJAX to be able to do multiple updates quickly without waiting for a full page reload.

The cell looks like this:

      <td style="min-width: 150px" id="goody_cell<%= blog.id %>">
        <%= render partial: "admin/goody_cell", locals: { blog: blog } %>
      </td>

With this as the partial:

<% if blog.variation_id %>
  <%= Variation.find(blog.variation_id).name %>
<% end %>

<%= simple_form_for(blog, url: update_goody_path(blog), remote: true, method: :patch, authenticity_token: true) do |f| %>
  <% variation_collection = [] %>
  <% Variation.all.each do |lm| %>
    <% variation_collection << ["#{lm.name}", "#{lm.id}"] %>
  <% end %>
  <div class="row text-left">
    <div class="form-group col-12 mb-0 pb-0">
      <%= f.input :variation_id, label: false, prompt: "Choose a Related Goody", input_html: { id: "lmFor" + blog.id.to_s, class: 'browser-default', onchange: "this.form.submit();" }, collection: variation_collection, required: false %>
    </div>
  </div> <!-- row -->
<% end %>

My blogs/update_goody.js.erb looks like this:

$('#goody_cell<%= blog.id %>').html('<%= j render partial: "admin/goody_cell", locals: { blog: @blog } %>');

And my controller method is like this:

  def update_goody
    @blog = Blog.friendly.find(params[:id])
    if @blog.update!(blog_params)
      respond_to do |format|
        format.js
      end
    else
      format.html { render :edit }
      format.json { render json: @blog.errors, status: :unprocessable_entity }
    end
  end

I have the route like this:

patch "blogs/:id/update_goody" => "blogs#update_goody", as: "update_goody"

When I try to update it, it does update the value, but before it renders the partial, I get an error saying:

ActionController::UnknownFormat - ActionController::UnknownFormat:
  app/controllers/blogs_controller.rb:178:in `update_goody'

I've looked at SO posts like this but they all say that the error was fixed by adding remote: true, which I already have.

Can anyone help me get this working?

Liz
  • 1,369
  • 2
  • 26
  • 61
  • isnt it update_goody.js sould be a update_goody.js.erb ? – roshiend May 22 '20 at 07:36
  • 1
    @roshiend Yes, it totally should. Unfortunately, this doesn't change the error I'm getting. – Liz May 22 '20 at 14:53
  • what your log says? try add format.html before format.js – roshiend May 22 '20 at 22:47
  • @roshiend It just says `BlogsController#update_goody is missing a template for this request format and variant.` if I do `format.html` before `format.js` (or after, for that matter). – Liz May 23 '20 at 00:33
  • looks like you are missing update_goody .html.erb file in views blogs – roshiend May 23 '20 at 08:35
  • @roshiend What would go on it? I want it to stay on the same page. Isn't that the point of Ajax? – Liz May 23 '20 at 10:21
  • When you are defined a controller action you should always have a spefic views for that action. in your case you, should have views/blogs/update_goody .html.erb .Rails initially look for that views when update_goody action triggered. you havent have update_goody.html.erb, thats why you are getting " missing a template" error. by setting respond_to |format| in your action you are telling controller to respond requests to js instead of html. by doing that so, it will override your update_goody.html.erb file and ignore html.erb file. but you should have update_goody.html.erb in views/bogs folder – roshiend May 23 '20 at 11:54
  • as you have set remote true in your form, rails knows you are looking for ajax request. in controller you are point to respond that request with js (respond_to |format|). if you remove remote true page will redirect to diffrent page that you set in your controller action (i.e respond_to do |format| format.html{redirect_to root_path }) – roshiend May 23 '20 at 12:03
  • Did you figure out a solution to this? – ricks Aug 11 '21 at 19:59
  • @ricks Not yet, no. It still "works" (if you refresh it manually) but no actual fix. – Liz Aug 15 '21 at 21:09

3 Answers3

1

instead of remote: true, use local: false (Rails 6)

0

make sure you have both update_goody.html.erb and update_goody.js.erb in your views/blogs folder.

you dont have to add anything to update_goody.html.erb as its not rendering at all. in your controller

def update_goody
    @blog = Blog.friendly.find(params[:id])
    if @blog.update!(blog_params)
      respond_to do |format|
        format.html
        format.js
      end
    else
      format.html { render :edit }
      format.json { render json: @blog.errors, status: :unprocessable_entity }
    end
  end

note that format.html in respond_to block. it dosent matter you add it or not as you are set remote: true in your form

refer this

roshiend
  • 554
  • 5
  • 12
  • This didn't throw an error, but it redirected me to the blank HTML page. – Liz May 23 '20 at 21:06
  • 1
    Nope. `respond_to do |format| format format.js do @blog = Blog.friendly.find(params[:id]) end` gives me the same `ActionController::UnknownFormat` error. – Liz May 23 '20 at 21:50
  • I haven't use simple form before but i think your remote true is not place right in the form.Take out remote true out of parentheses and place them like `<%=simple_form_for(blog, url: update_goody_path(blog), method: :patch, authenticity_token: true), remote: true do%>`this – roshiend May 26 '20 at 15:50
  • The syntax you suggested yields an unacceptable formatting error. I tried without parentheses entirely `<%= simple_form_for blog, url: update_goody_path(blog), method: :patch, authenticity_token: true, remote: true do |f| %>` but that just had the same `ActionController::UnknownFormat` error. – Liz May 26 '20 at 16:15
  • `<%=simple_form_for @blog, :url => {:controller => 'blogs', :action => 'update_goody', :method => patch,:authenticity_token => true,:remote => true } do |f|%>` – roshiend May 26 '20 at 20:10
  • It's now not even recognizing the route. – Liz May 31 '20 at 15:37
0

In my case i had to put redirect_to to render html

respond_to do |format|
  format.js 
  format.html { redirect_to update_goody_path }
end