【问题标题】:Dynamic dropdown in rails simple_formrails simple_form中的动态下拉列表
【发布时间】:2018-09-18 09:02:53
【问题描述】:

我的 rails 应用程序中有一个简单的 has_many 和 belongs_to 关系。我正在使用 simple_form 并希望根据用户选择的值动态更改下拉选项。

型号

 class Processor < ApplicationRecord
   has_many :processor_bank_accounts
 end

 class ProcessorBankAccount < ApplicationRecord
   belongs_to :processor
 end

表单输入

<%= simple_form_for [@customer, @transaction] do |f| %>
<%= f.error_notification %>

<div class="form-inputs">
  <%= f.input :status, :collection => ["payment request"], include_blank: false %>
  <%= f.input :processor, collection: @processors ,label_method: :name,value_method: :id,label: "Processor" , include_blank: false %>
  <%= f.input :processor_bank_account, collection: @bank_accounts , label_method: :bank_name, value_method: :id, label: "Processor Bank Account" , include_blank: true %>
  <%= f.input :tcurrency, collection: @currencies, include_blank: false, label: 'currency' %>
  <%= f.input :amount, as: :decimal, label: 'amount' %>
</div>

<div class="form-actions text-center">
  <%= f.button :submit, "Add transaction", class: "form-button"%>
</div>
<% end %>

所以本质上,我需要根据用户选择的处理器来填充 processor_bank_account 下拉列表。在控制台中,这只是:ProcessorBankAccount.where(processor: processor)。

需要使用 JS 加载选项并认为我需要使用 JSON 但不知道从这里去哪里

【问题讨论】:

    标签: javascript ruby-on-rails json ajax


    【解决方案1】:

    一种方法是使用 jQuery 对控制器操作进行 AJAX 调用,然后让 Rails 通过 erb 模板处理其余部分。

    因此,在您的页面上,使用表单通过 AJAX 调用操作,例如:

    <script>
        $(document).ready(function() {
            $('#processor_id').on('change', function() {
                $.ajax({
                    url: '/transactions/get_processor_bank_accounts',
                    type: 'GET',
                    data: {
                        processor_id: this.value
                    },
                    dataType: 'script',
                    error: function() {
                        alert('An error occurred retrieving bank accounts for the selected processor.');
                    }
                });
            });
        });
    </script>
    

    注意,#processor_id 是您的下拉控件的 ID。

    接下来,在控制器的操作中实例化银行账户:

    def get_processor_bank_accounts
      @processor_bank_accounts = ProcessorBankAccount.where(processor_id: params[:processor_id])
    end
    

    最后只需创建一个负责重新填充下拉列表的视图:

    $select_list = $('#processor_id');
    $select_list.empty();
    
    <% @processor_bank_accounts.each do |pba| %>
      $select_list.append($('<option value="<%= pba.id %>"><%= pba.name %></option>'));
    <% end %>
    

    【讨论】:

      【解决方案2】:

      我想出了以下解决方案:

      1) 向我的处理器控制器添加一个新方法,以 JSON 格式呈现第二个(动态)下拉列表的输入:

      def processor_bank_accounts
       render json: @processor.processor_bank_accounts.each do |bap|
       { id: bap.id, name: bap.name }
       end
      end
      

      2) 将此新功能分配给 config/routes 中的新路由:

      get 'api/bankaccounts', to: 'processors#processor_bank_accounts', as: 'bankaccounts'
      

      3) 创建一个 JS 函数以使用在第一个下拉列表中选择的处理器的 id 访问路由,并使用 JSON 数组中的项目填充第二个下拉列表:

      // select first dropdown
      const processor = document.getElementById("transaction_processor");
      // select second dropdown
      const bapSelect = document.getElementById("transaction_processor_bank_account");
      
      function update_baps(processor_id) {
       const url = `INSERTWEBURLHERE/api/bankaccounts?id=${processor_id}`;
       fetch(url)
       .then(response => response.json())
       .then((data) => {
        bapSelect.innerHTML = ""; // clear second dropdown
        data.forEach((bap) => { // go through all the BAPs
        const elem = `<option value="${bap.id}">${bap.bank_name}</option>`; // create option elements to insert into the second dropdown, bank_name is the chosen label method in the form
        bapSelect.insertAdjacentHTML("beforeend", elem); // insert options into the dropdown
        });
       });
      }
      

      4)当第一个下拉字段改变时触发JS:

      processor.addEventListener('change', function () {
       update_baps(parseInt(processor.value));
      });
      

      【讨论】:

        【解决方案3】:

        您应该将id 添加到选择中,以便您可以从脚本中识别它们。

        $('select#processor').on('change', function() {
              var processor_id = this.value;
              var processor_bank_account = $('select#processor_bank_account')
        
              $.ajax({
                type: "GET", 
                url: <%= your_path %> ,
                data: { processor_id: processor_id },
                success: function(data, textStatus, jqXHR){
                  processor_bank_account.empty();
                  var option = new Option(data.bank_name, data.id, false, false);
                  processor_bank_account.append(option);
                },
                error: function(jqXHR, textStatus, errorThrown){...}
              })
         });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-13
          相关资源
          最近更新 更多