从嵌套表单发出组合框中的更新类

时间:2014-08-12 22:56:57

标签: ruby-on-rails ruby nested-forms nested-attributes ruby-on-rails-2

我创建了一个组合框,显示供应商,因此当选择供应商时将更新显示购买的div,显示购买后将以组合框形式进行嵌套,因此当我选择购买时将显示所选购买的金额。

问题在于,当我选择购买时,仅在第一行中有效,当我选择另一个组合框线时,显示所选择的第一个组合框的数量。

这是我的表格

suppliers
  |id|  |name|
   1     Supplier A
   2     Supplier B

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 

purchase_products
   |id|  |name|    |price_sale| 
     1     XP          1000        
     2     VISTA       2000         

supplier_products
   |id|  |supplier_id|   |amount| |purchase_product_id
     1     1                1000        1
     2     1                2000        1 
     3     2                3000        2 

这是控制器/app/controller/purchase_product_controller.rb

class ShoppingDocumentController < ApplicationController
 def new
   @document = ShoppingDocument.new
   @suppliers= Supplier.all    
   @products = SupplierProduct.find(:all,:conditions=>['supplier_id =? ',params[:suppliers] ],:group=>['purchase_product_id'])
   @purchases= SupplierProduct.find(:all,:conditions=>['supplier_id =? ',params[:suppliers] ],:group=>['purchase_product_id'])

   4.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_supplier_div
   @products = SupplierProduct.find(:all,:conditions=>['supplier_id =? ',params[:suppliers] ],:group=>['purchase_product_id'])
 end

 def update_product_div
   @purchases= SupplierProduct.find(:all,:conditions=>['purchase_product_id =? ',params[:product] ],:group=>['purchase_product_id'])
 end

end

这里的型号:

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
   has_many :supplier_products
end

class SupplierProduct < ActiveRecord::Base
   belongs_to :purchase_product
end

以下是视图:/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_supplier_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 %>

以下是部分视图:/app/view/shopping_document/_shopping_product_fields.html.erb

<div class="fields">
 <table>
  <tr><td><%= f.text_field :qty , :size=>"9"  %></td>
      <td><%= select_tag "product","<option value=\"\">Select</option>"+options_for_select(@products.map { |c| [c.amount, c.id] }),:onchange=>remote_function(:url=>{:controller=>"shopping_document",:action=>"update_product_div"},:before=>"load_close('loading_condition')",:success=>"load_off('loading_condition')",:with=>"'product=' + $('product').value"),:class=>"product" %></td>
      <td><%= f.select :purchase_product_id,"<option value=\"\">Select</option>"+options_for_select(@purchases.map { |c| [c.amount, c.id] }), {}, :class => "helping" %></td> 
      <td><%= link_to_remove_fields image_tag("standard/delete.png",:border=>0,:size=>"14x14"), f %></td>
  </tr>
 </table>
</div>

以下是rjs:/app/view/shopping_document/_update_supplier_div.rjs

page.select('.product').each do |select_tag|
  page.replace_html select_tag, "<option value=\"\">Select</option>"+options_for_select(@products.map{|c| [c.purchase_product.name, c.purchase_product_id]})
end

以下是rjs:/app/view/shopping_document/_update_product_div.rjs

page.select('.helping').each do |select_tag|
  page.replace_html select_tag,"<option value=\"\">Select</option>"+options_for_select(@purchases.map { |c| [c.amount, c.id] })
end

在第一行中不更新其他行只是更新。

请有人帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

问题是,在更新产品时,您始终会向控制器操作发送相同的值。

从/app/view/shopping_document/_shopping_product_fields.html.erb partial看看这一行:

<%= select_tag "product",
  "<option value=\"\">Select</option>"+
  options_for_select(@products.map { |c| [c.amount, c.id] }),
  :onchange=> remote_function(
    :url= {:controller => "shopping_document", :action=>"update_product_div"}, 
    :before => "load_close('loading_condition')", 
    :success => "load_off('loading_condition')", 
    :with => "'product=' + $('product').value"),
    :class=>"product" %>

根据我的记忆,在prototype.js中,当你使用$("something")时,它会在你的DOM树中找到id = 'someting'

的第一个元素

您在$('product')子句中使用with的事实使它始终将第一行的select标记值发送到服务器,这是错误的。

您应该使用$(this)来确保它是正在发送的current选择的值。所以你需要替换:

:with => "'product=' + $('product').value"

有了这个:

:with => "'product=' + $(this).value"

另一个问题是,当您更改产品时,它会立即更改所有价格,并且您只希望该产品的价格发生变化。因此,您需要更具体地了解rjs中要更改的行。

我们要做的就是改变你返回的rjs。这个rjs现在只分配一个javascript变量:

page.assign "prices_for_product", "<option value=\"\">Select</option>" +  options_for_select(@purchases.map { |c| [c.amount, c.id] })

现在我们必须创建一个新的javascript方法,它将使用该变量中的值并将其设置为当前元素。为此,您需要在定义load_closeload_off的javascript文件中添加以下方法:

function update_prices_for_product(prices_select_tag){
  prices_select_tag.innerHTML = prices_for_product;
}

但是当AJAX调用成功时我们仍需要调用此方法,因此我们将把它添加到:success参数。

:success => "load_off('loading_condition'); update_prices_for_product($(this));"

还有一些让我很困惑的事情。您将来自嵌套表单的supplier_product_id发送到您的控制器,并将其作为purchase_product_id注入您的查询,所有这些都在SupplierProduct表上调用。从我在数据模型上看到的不正确的东西,我必须承认我真的很困惑。请参阅update_product_div操作:

SupplierProduct.find(:all,:conditions=>['purchase_product_id =? ',params[:product] ],:group=>['purchase_product_id'])

您正在寻找的是为产品完成的所有购买。那会更像是:

PurchaseProduct.find(:all,:conditions=>['supplier_product_id =? ', params[:product]])

您显然错过了supplier_product_id表格中的purchase_products列。

这就像我能为你做的那样,让我们​​希望别人跳进来......

我必须说这不是一个好习惯,你应该一直使用unobstrusive javascript并升级到jquery。此外,使用更新的Rails版本,因为没有多少人仍然可以帮助您使用Rails 2.3 ...

这个答案唯一的好处是它可能会起作用......