1

On an index page, I'd have a form to create a new object. On submitting the form, I'd like to update the page with the new object without the page refreshing. The form submits and the object is created but the page is not updated. The form is hidden which is the desired affect but the new object does not display. The logs show the stack trace as

Started POST "/products" for ::1 at 2015-06-27 18:38:14 +0100
Processing by ProductsController#create as JS
Parameters: {"utf8"=>"✓", "product"=>{"name"=>"Pets"}, "button"=>""}
User Load (1.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1  [["id", 2]]
(0.2ms)  BEGIN
SQL (0.4ms)  INSERT INTO products" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "Pets"], ["created_at", "2015-06-27 17:38:14.418558"], ["updated_at", "2015-06-27 17:38:14.418558"]]  
(6.1ms)  COMMIT
(0.4ms)  SELECT COUNT(*) FROM "items" WHERE "items"."product_id" = $1    [["product_id", 83]]
Rendered products/_product.haml (1.4ms)
Rendered products/create.js.erb within layouts/admin (2.7ms)
Rendered products/index.haml within layouts/admin (12.8ms)
Rendered layouts/_shim.html.erb (0.1ms)
Rendered layouts/_header.haml (0.6ms)
Rendered layouts/_footer.haml (0.1ms)
Completed 200 OK in 139ms (Views: 134.7ms | ActiveRecord: 2.1ms)

the form is in index.haml

%div{class: "col-md-4 col-md-offset-2 product-list"}
  - @products.each do |product|
    = render 'product', product: product

%div{class: "col-md-4"}
  .btn.btn-success.btn-sm.add-product
  Add a product

.add-product-form
  = form_for @product, remote: true, html: {class: "product disabled"} do |f|

  .product-add
    .form-group
      = f.label :name 
      = f.text_field :name, class: "form-control"
    .form-group
      .controls
        = f.button '+ Add', class: 'btn btn-success save-product'
        .btn.btn-warning.product-cancel
          Cancel

products.js.coffee

$ ->
  $(document).on "click", ".save-product", ->
    $('.add-product-form').hide()

products_controller.rb

def create
  @product = Product.new(product_params)
  if @product.save
    respond_to do |format|
      format.html
      format.js
    end
  end
end

create.js.erb

$(".product-list").append("<%= j render 'product', product: @product} %>");

_product.haml

%h4
  = link_to product_url(product.id) do
    = product.name.capitalize

I'm fairly new to js/coffeescript. How do I get the view to update with the new item, which I can see has been saved?

margo
  • 2,927
  • 1
  • 14
  • 31
  • At which line the error shows up? – Pavan Jun 27 '15 at 16:19
  • line 2 of _product.haml – margo Jun 27 '15 at 16:27
  • Hard to tell for sure, but I think when you call this line ```$(".product-list").append("<%= j render 'product', locals: {product: @product} %>");``` what your'e doing is passing a Product Class instead of an instance, into the template. – Kirill Jun 27 '15 at 18:10

1 Answers1

1

Your render line in the js is wrong, either write

render 'product', product: @product

Or write

render partial: 'product', locals: { product: @product }
nathanvda
  • 49,707
  • 13
  • 117
  • 139
  • good spot, I just spotted that too. So now I'm not getting any 500 error or any error at all. But the new product is not being shown. – margo Jun 27 '15 at 18:21
  • Alternative method, instead of doing your submit via rails, submit via an AJAX request from the page, and then on the rails side do ```render :json => { results => (render_to_string partial: "product", locals: {product: @product}) } ``` and have your JavaScript interpret append that response to the page. Perhaps a personal preference, but makes tracking bits much easier. – Kirill Jun 27 '15 at 18:43
  • Margo: from the code you show everything seems ok. Things to look for: 1) the jquery selector does not return anything (but it seems ok), 2) there is an error in the javascript code. The easy way to test this: open the console in the browser, open the network tab, do the ajax, click the request, copy the response and run the response in the javascript console: then you will see the error. Good luck! – nathanvda Jun 27 '15 at 22:22
  • @Kirill: which means rendering views in the js side, which is a completely different approach, and not an easy switch. Imho a simple case like this is still easier like Margo is handling it now. – nathanvda Jun 27 '15 at 22:24
  • Weird, I can just execute that piece of code in my console without error. Did you copy it exactly here? Maybe make it render as code so it is rendered verbatim. – nathanvda Jun 29 '15 at 09:43