【问题标题】:Dynamically adding prepopulated nested forms using cocoon and rails3-jquery-autocomplete使用 cocoon 和 rails3-jquery-autocomplete 动态添加预填充的嵌套表单
【发布时间】:2013-02-25 17:35:40
【问题描述】:

感谢您的宝贵时间。

我正在使用 rails 3.2,我正在使用 gems simple_formcocoonrails3-jquery-autocomplete

我有以下型号Machine、Part、PartUsage、MachineCosting 和 PartCosting

具有多对多关联的机器和零件模型。

    class Machine < ActiveRecord::Base
      attr_accessible :name

      has_many :part_usages
      has_many :parts, :through => :part_usage
    end

    class Part < ActiveRecord::Base
      attr_accessible :name
    end

    class PartUsage < ActiveRecord::Base
      attr_accessible :machine_id, 
                      :part_id
      belongs_to :part
      belongs_to :machine
    end

具有一对多关联的机器成本和零件成本模型。

    class MachineCosting < ActiveRecord::Base

       attr_accessible :machine_id,
                       :total_cost,
                       :machine_name,
                       :part_costings_attributes

       attr_accessor :machine_name                

       has_many :part_costings, :dependent => :destroy

       accepts_nested_attributes_for :part_costings, :allow_destroy => true    

       def machine_name
         self.machine.try(:name)
       end

    end

    class PartCosting < ActiveRecord::Base
      attr_accessible :part_id,
                      :part_name,
                      :cost

      attr_accessor :part_name

      belongs_to :machine_costing
      belongs_to :part

      def part_name
        self.part.try(:name)
      end
    end

MachineCosting 表格

意见/machine_costings/_form.html.erb
   <%= simple_form_for(@machine_costing, :html => {:multipart => true}) do |f| %>

     <%= f.input :machine_id, :url => autocomplete_machine_id_machines_path, 
            :as => :autocomplete %>

        <!-- HERE, WHENEVER I SELECT A MACHINE, I WANT TO ADD NESTED-FORMS FOR 
     PARTCOSTINGS CORRESPONDING TO ALL THE PARTS OF THE MACHINE I JUST SELECTED.-->

        <%= f.simple_fields_for :part_costings do |part_costing|%>   
          <%= render 'part_costings/part_costing_fields', :f => part_costing %>
        <% end %>

   <% end %>

请建议我如何在字段中选择 machine_id 后使用 javascript 为 PartCostings 填充和动态添加固定字段数。

我很乐意提供更多信息。

再次感谢!!

【问题讨论】:

    标签: javascript jquery ruby-on-rails-3 simple-form cocoon-gem


    【解决方案1】:

    首先,总结一下我的方法。

    • 在 MachineCosting 表单中,使用“rails3-jquery-autopopulate”gem 按名称搜索机器。
    • 破解 MachineController 以将“零件信息”与匹配的机器一起以 json 形式发送。
    • 当用户选择机器时,使用 javascript 为 PartCostings 添加nested_forms,并使用以 json 形式接收的数据部分填充它们。

    下面是我的做法(代码部分)。

    views/machine_costings/_form.html.erb

        <%= simple_form_for(@machine_costing, :html => {:multipart => true}) do |f| %>
            <%= f.error_notification %>
    
            <%= f.input :machine_name, :url => autocomplete_machine_name_machines_path, 
                      :as => :autocomplete, :input_html => { :id_element   =>  "#machine_costing_machine_id"} %>
    
            <%= f.association :machine, :as => :hidden %>
    
            <div id='part_costings'>
              <%= f.simple_fields_for(:part_costings) do |part_costing|%>   
                <%= render 'part_costings/part_costing_fields', :f => part_costing %>
              <% end %> 
    
              <div class="links hidden">
                <%= link_to_add_association 'Add part costings', f, :part_costings, 
                  :partial => 'part_costings/part_costing_fields' %>
              </div>
            </div>
    
            <%= f.button :submit%>
        <% end %>
    

    views/part_costings/_part_costing_fields.html.erb

        <div class= 'nested-fields'>    
                <!-- DO NOT CHANGE THE ORDER OF ATTRIBUTES ELSE machine_costing.js WILL FAIL -->
               <%= f.input :part_id, :as=> :hidden %>
               <%= f.text_field :part_name, :disabled => 'disabled' %>           
               <%= f.input :cost %>
               <%= link_to_remove_association '<i class="icon-remove"></i>'.html_safe, f ,:class =>"part_costing_remove" %>
        </div> 
    

    控制器/machines_controller.rb

        class MachinesController < ApplicationController
    
          # OVER RIDING THIS BY OWN METHOD
          # autocomplete :machine, :name, :full=> true, :extra_data => [:machine_id]
    
          def autocomplete_machine_name
            respond_to do |format|
              format.json {
                @machines = Machine.where("name ilike ?", "%#{params[:term]}%")
    
                render json: json_for_autocomplete_machines(@machines)
              }
            end
          end
    
          def json_for_autocomplete_machines(machines)
            machines.collect do |machine|
    
              parts = Hash.new
              unless machine.part_usages.empty?
                machine.part_usages.each do |part_usage|
                  parts[part_usage.part.id] = part_usage.part.name
                end
              end
    
              hash = {"id" => machine.id.to_s, "value" => machine.name,
                                "parts" => parts} 
    
              hash
            end
          end 
    
          #
          #
          #
    
        end
    

    这里是 javascript 部分。

    assest/javascripts/machine_costings.js

        $(function() {
    
          // Part Costings
          var part_id;
          var part_name;
    
          $('#machine_costing_machine_name').bind('railsAutocomplete.select', function(event, data){
            console.debug("Machine selected...");
            parts = data.item.parts;
            console.debug("Removing existing part_costings...");
            $('.part_costing_remove').click();
            console.debug("Adding part_costings...");
            for(var id in parts) {
             part_id = id;
             part_name = parts[id];
             $('.add_fields').click();
            }
            console.debug("Done adding all part_costings...");
          });
    
          $('#part_costings').bind('cocoon:after-insert', function(e, part_costing) {
            part_costing[0].getElementsByTagName('input')[0].value = part_id;
            part_costing[0].getElementsByTagName('input')[1].value = part_name;
            console.debug("Added part_costing...");
          });
    
        });
    

    routes.rb

      resources :machines  do
          get :autocomplete_machine_name, :on => :collection
      end
    

    javascript解决方案的关键点是......

    1. 来自 rail3-jquery-autocomplete gem 的方法“bind('railsAutocomplete.select', function(event, data)”。

    2. 来自 cocoon gem 的方法“bind('cocoon:after-insert', function(e, part_costing)”。

    就是这样。 如果您有任何建议,请告诉我。谢谢:)

    【讨论】:

      猜你喜欢
      • 2011-08-30
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      • 2012-04-28
      • 2012-06-28
      • 2020-12-10
      • 1970-01-01
      • 2018-04-22
      相关资源
      最近更新 更多