Search code examples
ruby-on-railsrubyruby-on-rails-2

Issue replacing the information in nested form according a select box


I followed thos steps http://railscasts.com/episodes/197-nested-model-form-part-2

I created a select box with suppliers so when I select a supplier will show all purchases that has a supplier selected updating the nested form.

Here my tables

suppliers
  |id|  |name|
   1     AAAA
   2     BBBB

shopping_documents
  |id|  |supplier_id|   
   1         1
   2         2

shopping_products
   |id|  |shopping_document_id| |qty| |purchase_product_id|
     1             1              1           1
     2             1              1           2 
     3             2              1           3

purchase_products
   |id|  |name| |description|   |cost| |supplier_id|
     1     XP     CD-ROM         1000        1
     2     VISTA  CD-ROM         2000        1
     3     W7     CD-ROM         3000        2          

Here is the controller /app/controller/purchase_product_controller.rb

class ShoppingDocumentController < ApplicationController
 def new
   @document = ShoppingDocument.new
   @suppliers= Supplier.all    
   @purchases = PurchaseProduct.all  
   1.times do
    shopping_product = @document.shopping_products.build
   end 
 end

 def create
   @document = ShoppingDocument.new(params[:shopping_document])
   if @document.save
     flash[:notice] = "Successfully created document."
     redirect_to :action=>"index"
   else
     render :action => 'new'
   end
 end

 def update_nested_div
    @purchases= PurchaseProduct.find(:all,:conditions=>['supplier_id =? ',params[:suppliers] ])
 end

end

Here models:

class ShoppingDocument < ActiveRecord::Base
   has_many :shopping_products
   accepts_nested_attributes_for :shopping_products ,:allow_destroy => true
end

class ShoppingProduct < ActiveRecord::Base
   belongs_to :shopping_document
   belongs_to :purchase_product
end

class PurchaseProduct < ActiveRecord::Base
   has_many :shopping_products
end

Here is the view: /app/view/purchase_product/new.html.erb

<% form_for @document, :url => {:controller=>"shopping_document",:action=>'create'} do |f|  %>
   Name: <%= select_tag 'suppliers',"<option value=\"\">Select</option>"+options_for_select(@suppliers.collect {|t| [t.name,t.id]} ),:onchange=>remote_function(:url=>{:controller=>"shopping_document",:action=>"update_nested_div"},:with=>"'suppliers=' + $('suppliers').value"),:name=>"shopping_document[supplier_id]" %>    
   <% f.fields_for :shopping_products do |builder| %>
     <%= render "shopping_product_fields", :f => builder %>
   <% end %>
   <p><%= link_to_add_fields "Add Product", f, :shopping_products %></p>
   <p><%= f.submit "Submit" %></p>
<% end %>

Here is the partial view: /app/view/shopping_document/_shopping_product_fields.html.erb

<div class="nested_form">
   <%= f.select :purchase_product_id,@purchases.map { |c| [c.cost, c.id] },{},:id=>"helping" %> %>   
   Quantity: <%= f.text_field :qty  %> <%= link_to_remove_fields "remove", f %> 
</div>

Here is the view rjs : /app/view/shopping_document/_update_nested_div.rjs

page.replace_html 'helping', options_for_select(@purchases.map{|c| [c.cost, c.id]})

Is working perfect but is just working with the first nested select box , If I add click on "Add Product" the second or next or more won't be according the supplier selected and will show all suppliers.

Please somebody can help me with this issue?

Is just working only on the first nested select box if I add another won't show values according the supplier selected just show all .


Solution

  • EDIT 8/11 9pm

    You can set a class instead of an id on the select tag you want to change the options of based on the supplier selection.

    <%= f.select :purchase_product_id,@purchases.map { |c| [c.cost, c.id] }, {}, :class => "helping" %>
    

    And then change your /app/view/shopping_document/_update_nested_div.rjs with the following:

    page.select('.helping').each do |select_tag|
      page.replace_html select_tag, options_for_select(@purchases.map{|c| [c.cost, c.id]})
    end
    

    The problem you had was that replace_html works on the first element it finds with the id "helping". With a class and page.select, we get a collection of select tags from which we have to the options by iterating on them.

    The pattern I use is described in the Rails 2.3.8 api documentation. Check it out for the other methods available.