Динамическое добавление предварительно заполненных вложенных форм с использованием кокона и rails3-jquery-autocomplete

Спасибо за ваше время.

Я работаю над rails 3.2 и использую драгоценные камни simple_form, cocoon и rails3-jquery. -автозаполнение.

У меня есть следующие модели 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

Модели MachineCosting и PartCosting с ассоциацией «один ко многим».

    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

views/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 %>

Пожалуйста, предложите, как я могу заполнить и динамически добавить фиксированное количество полей для PartCostings, используя javascript после того, как в поле выбран machine_id.

Я был бы рад предоставить любую дополнительную информацию.

Спасибо еще раз!!


person Bot    schedule 25.02.2013    source источник


Ответы (1)


Во-первых, краткое изложение моего подхода.

  • В форме MachineCosting используйте гем «rails3-jquery-autopopulate» для поиска машин по их имени.
  • Взломайте MachineController, чтобы также отправлять «Информацию о деталях» вместе с соответствующими машинами в форме json.
  • Когда пользователь выбирает машину, используйте javascript, чтобы добавить вложенные_формы для PartCostings и частично заполнить их, используя данные, полученные в форме json.

Теперь вот как я это сделал (часть кода).

просмотры/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.

оценка/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...");
      });

    });

маршруты.rb

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

Критические точки в решении javascript...

  1. Метод «bind('railsAutocomplete.select', function(event, data)» из гема rail3-jquery-autocomplete.

  2. Метод «bind('cocoon:after-insert', function(e, part_costing)» из драгоценного камня кокона.

Это все. Пожалуйста, дайте мне знать, если у вас есть предложения. Спасибо :)

person Bot    schedule 07.03.2013