【问题标题】:jQuery updating rails form partial based on selected item in drop downjQuery根据下拉列表中的选定项目更新rails表单
【发布时间】:2015-08-13 20:50:21
【问题描述】:

在我的 rails 应用程序中,我有一个下拉菜单,用户可以选择一个帐户进行付款:

    //_payment.html.erb

     <div class="field" id="payment-to-account">
      <%= f.label 'Payment To:' %><br>
      <%= f.collection_select :to_account_id, @liability_account_payment_list, :id, :account_details, {include_blank: 'Please Select'} %>
    </div>

当用户选择一个帐户时,我会根据他们的选择在此表单中呈现部分内容:

    //_payment.html.erb
    <%= form_for(@transaction, 
             as: :transaction,
             url: 
             @transaction.id ? account_transaction_path(@account, @transaction) : account_transactions_path) do |f| %>

    ...

    <% @f = f %>
    <div id="to-account-form" style="display:none;"></div>

    ...
    <script>

    jQuery(function(){

      $("#payment-to-account").change(function() {
        var selected_item = $( "#payment-to-account option:selected" ).text();
        var selected_item_index = $( "#payment-to-account option:selected" ).index(); 
        //looks for account type in parentheses followed by space moneysign " $"
        var regExp = /\(([^)]+)\)\s\$/;
        var matches = regExp.exec(selected_item);

    // array of account ids in order of list
    var payment_account_ids = <%= raw @payment_list_ids %>;

    switch (matches[1]) {
      case 'Mortgage':
        $('#to-account-form').html("<%= j render 'payment_to_mortgage', f: @f %>");
        $('#to-account-form').slideDown(350);
        break;
      case 'PersonalLoan':
      case 'CreditCard':
      case 'StudentLoan':
      case 'OtherLiability':
        $('#to-account-form').html("<%= j render 'payment_to_all_other_liabilities', f: @f %>");
        $('#to-account-form').slideDown(350);
        break;
      default:
        $('#to-account-form').html("<br>" + "Contact support, an error has occurred");
        $('#to-account-form').slideDown(350);
        }
      });

    });

    </script>

现在它会根据选择呈现正确的部分,但是当部分加载时,我需要来自帐户模型的更多信息。我创建了一个名为 find_pay_to_account 的方法,该方法在 Accounts 模型中输入选定的帐户 ID,该模型根据 ID 查找帐户。

当用户从下拉列表中选择帐户时,我希望在加载的部分上调用该方法,以便在用户提交表单之前向用户显示有关他们正在付款的帐户的其他信息。但我不知道怎么做。我想在我的 jQuery switch 语句中添加类似的内容。

    selected_account_id = payment_account_ids[selected_item_index-1]
    @payment_to_account = Account.find_pay_to_account(selected_account_id)

由于 rails 在后台预加载了部分,因此在 case 语句中对我的部分渲染进行以下更改仍然无效:

从这里

  $('#to-account-form').html("<%= j render 'payment_to_mortgage', f: @f %>");

到这里

  $('#to-account-form').html("<%= j render 'payment_to_mortgage', f: @f, @payment_to_account: @payment_to_account %>");

我做了一些搜索,发现使用 AJAX 可能会有所帮助:
Pragmatic Studio
Rails Cast

但我正在尝试访问模型,而不是控制器,并且我正在尝试更新部分表单。这样做的正确方法是什么?

这是显示用户流程的图片。在最后一张图片中可以看到我正在尝试更新的示例。选择抵押账户时,需要显示抵押账户的最低还款额。现在它显示为零,因为部分渲染使用了来自 BOA 种子 0214 的所有信息。

【问题讨论】:

    标签: javascript jquery ruby-on-rails ajax


    【解决方案1】:

    如果您想从前端 javascript 中的模型访问记录信息,您确实需要设置一个小 api 来查询数据库以获取该信息。在 ajax 中会是这样的

    function processDataFunction(data){
      console.log(data)
    }
    
    $.ajax({
      type: "GET",
      dataType: "json",
      url: "/some-path/:some_id",
      success: processDataFunction(data){}
    });
    
    
    
    #config/routes.rb
    Rails.application.routes.draw do
      get "/some-path/:some_id", to: "some_controller#some_view", :defaults => { :format => :json }
    end
    
    #app/controllers/some_controller.rb
    class SomeController < ApplicationController
      def some_view
        @some_records = SomeModel.find_by_id(params[:some_id])
        respond_to do |format|
          format.json { render json: @some_records }
        end
      end
    end
    

    【讨论】:

      【解决方案2】:

      为了在不进行其他控制器操作的情况下访问渲染部分中的信息,我收集了原始操作中可能需要的所有数据。这样我就可以在不更改路由和执行 ajax 请求的情况下获得我正在寻找的确切结果。

      为此,我向控制器的新操作添加了方法。您可以从我最初的问题中看到,我可能需要信息的所有帐户都在下拉菜单中的变量中:

      @liability_account_payment_list
      

      这是下拉菜单从中获取信息的地方

      该变量位于事务控制器的新操作中。所以我创建了另一个变量,在上述变量之后的行上存储一个数组:

      @liability_accounts_payment_list_minimum_payments = @liability_account_payment_list.map {|account| account.minimum_payment.to_f + account.minimum_escrow_payment.to_f}
      

      这个新变量是所有账户最低还款额的数组,按照用户从下拉菜单中列出的顺序排列。

      然后我把页面上的jQuery改成如下

      //_payments.html.erb
      <script>
      
      jQuery(function(){
      
        $("#payment-to-account").change(function() {
          var selected_item = $( "#payment-to-account option:selected" ).text();
          var selected_item_index = $( "#payment-to-account option:selected" ).index(); 
          //looks for something in parentheses followed by space moneysign " $"
          var regExp = /\(([^)]+)\)\s\$/;
          var matches = regExp.exec(selected_item);
      
          // array of minimum payments from accounts in list converted from ruby to js
          var min_payments = <%= raw @liability_accounts_payment_list_minimum_payments %>;
          // set the js variable to the appropriate minimum payment
          var selected_account_min_payment = min_payments[selected_item_index-1];
      
          switch (matches[1]) {
            case 'Mortgage':
              $('#to-account-form').html("<%= j render 'payment_to_mortgage', f: @f %>");
      
              $("#min-payment-field-hidden").val(selected_account_min_payment);
              $("#min-payment-field").html(selected_account_min_payment);
      
              $('#to-account-form').slideDown(350);
              break;
            case 'PersonalLoan':
            case 'CreditCard':
            case 'StudentLoan':
            case 'OtherLiability':
              $('#to-account-form').html("<%= j render 'payment_to_all_other_liabilities', f: @f %>");
      
              $("#min-payment-field-hidden").val(selected_account_min_payment);
              $("#min-payment-field").html(selected_account_min_payment);
      
              $('#to-account-form').slideDown(350);
              break;
            default:
              $('#to-account-form').html("<br>" + "Contact support, an error has occurred");
              $('#to-account-form').slideDown(350);
          }
        });
      
      });
      
      </script>
      

      具有 min-payment-field-hidden 的行是因为设置两个具有相同 id 的不同 div 不起作用。一个 div 用于设置 hidden_​​field,另一个用于向用户显示值是什么。

      //_payment.html.erb
      <-- To make sure the appropriate minimum payment is submitted to controller -->
      <%= f.hidden_field :amount, :id => "min-payment-field-hidden" %>
      
      <div>
        <%= f.label "Minimum Payment" %>
        <div id="min-payment-field"></div>
      </div>
      

      如果你看一下我的 switch 语句,你可以看到我用这些行设置了上面的值:

      $("#min-payment-field-hidden").val(selected_account_min_payment);
      $("#min-payment-field").html(selected_account_min_payment);
      

      现在用户可以看到他们从下拉列表中选择的特定帐户的最低付款额。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-09
        • 1970-01-01
        相关资源
        最近更新 更多