且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

jQuery更新rails表格部分基于下拉列表中的选定项目

更新时间:2023-02-11 20:04:39

访问渲染部分中的信息而不再创建另一部分控制器动作,我收集了原始动作中可能需要的所有数据。这样我就可以得到我正在寻找的确切结果,而无需更改我的路线和执行ajax请求。



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

  @liability_account_payment_list 

这是下拉菜单从


$获取信息的地方b $ b



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

  @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选项:selected)。text();
var selected_item_index = $(#payment-to-account option:selected)。index();
//查找括号中的内容后面跟着空格币$
var regExp = / \(([^]] +)\)\\\\ $ /;
var matches = regExp.exec( selected_item);

//从红宝石转换为js
var min_payments =<%= raw @liability_accounts_payment_list_minimum_payments%&gt ;;
//列表中的帐户的最低付款数组将js变量设置为适当的最小付款
var selected_account_min_payment = min_payments [selected_item_index-1];

switch(匹配[1]){
case'抵押贷款':
$('#to-account-form')。html(<%= j render'fayment_to_mortgage',f:@f%>);

$(#min - 付款 - 现场hidd EN)VAL(selected_account_min_payment)。
$(#min-payment-field)。html(selected_account_min_payment);

$('#to-account-form')。slideDown(350);
休息;
案例'PersonalLoan':
案例'CreditCard':
案例'StudentLoan':
案例'OtherLiability':
$('#to-account-form' ).html(<%= j render'dayment_to_all_other_liability',f:@f%>);

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

$('#to-account-form')。slideDown(350);
休息;
默认值:
$('#to-account-form')。html(< br>+联系支持,发生错误);
$('#to-account-form')。slideDown(350);
}
});

});

< / script>

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

  // _ payment.html。 erb 
< - 确保向控制器提交适当的最低付款额 - >
<%= f.hidden_​​field:amount,:id => min-payment-field-hidden%>

< div>
<%= f.label最低付款额%>
< div id =min-payment-field>< / div>
< / div>

如果查看我的switch语句,可以看到我用以下行设置了上述值: / p>

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

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




In my rails app I have a dropdown menu that a user can select an account to make a payment to:

    //_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>

When the user selects a account I render a partial inside of this form based on their selection:

    //_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>

Right now it renders the correct partial based on the selection, but when that partial loads I need more information from the account model. I created a method called find_pay_to_account that take the input selected account id in the Accounts model that looks for the account based on the id.

When the user selects and account from the drop down, I'd like that method called on the partial that is loaded so I can show the user additional information about the account they are making a payment to before they submit the form. But I don't know how. I wanted to add something like this to my jQuery switch statement.

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

Since rails preloads the partials in the background, making the following change to my partial render in the case statements still wont work:

From this

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

To this

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

I did some searching and found that with AJAX might be able to help:
Pragmatic Studio
Rails Cast

But i'm trying to access the model, not the controller and I'm trying to update a form partial. What is the correct way to do this?

Here are pics that show the user flow. An example of what I'm trying to update can be seen in the last pic. When the mortgage account is selected, it needs to show the minimum payment for the mortgage account. Right now it says zero because the partials rendering with all the information from BOA seed 0214.

To access the information in the rendered partial without making another controller action, I collected all data I might need in the original action. That way I could get the exact result I was looking for without changing my routes and doing ajax request.

To do this I added methods to the controller new action. You can see from my original question, all accounts I may need information for are in the variable that is in the dropdown menu:

@liability_account_payment_list

This is where the dropdown menu gets its information from

That variable is in the Transaction controller new action. So I created another variable storing an array on the line after the above variable:

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

This new variable is an array of all the accounts minimum payments in the order they are listed in the dropdown menu the user will select from.

Then I changed the jQuery on the page to the following

//_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>

The lines that have min-payment-field-hidden are because setting two different divs with the same id does not work. One div is being used to set hidden_field, the other is showing the user what the value is.

//_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>

If you look at my switch statement, you can see I set the above value with these lines:

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

Now the user can see the minimum payment for the specific account they choose from the dropdown.