How to get input value with Cocoon and Javascript?

两盒软妹~` 提交于 2019-12-12 05:01:57

问题


I try to implement a simple order management system where users can create new commands and add two types of product to them. When a user select a product and enter a quantity, the total price is dynamically calculated and displayed in the last field. For adding a new product line to the order, I use the gem Cocoon.

My problem is that I'm not able to calculate the total price for every new product added with Cocoon. Every time I enter a quantity, I get the total price from the first line. Is there anyone who can help me to resolve this issue ?

This is my view/orders/_form.html.erb :

<%= form_for @order do |f| %>

    <div id="item">
       <%= f.fields_for :line_items do |li| %>
          <%= render partial: "line_item_fields", locals: {f: li} %>
       <% end %>
       <div class="link form-group"><%= link_to_add_association "Ajouter un produit", f, :line_items %></div>
    </div>

    <div class="actions">
        <%= f.submit "Commander", class: "btn btn-primary" %> 
    </div>

<% end %>

This is my view/orders/_line_items.html.erb :

<div class="nested-fields form-inline">

   <div class="form-group">
     <%= f.label "Type de produit : " %>
     <% if current_user.recruiter.company.pricing_profile.name == ("JobCards single" || "TM Basic") %>
       <%= f.select(:name, options_for_select([['Job card', 'Job card']]), {}, {class: "product_name"}) %>
     <% else %>
       <%= f.select(:name, options_for_select([['Job card', 'Job card'], ['Job page', 'Job page']]), {}, {class: "product_name"}) %>
     <% end %>
   </div>

   <div class="form-group">
     <%= f.label "Quantité : " %>
     <%= f.text_field :quantity, class: "quantity" %>
   </div>

   <div class="form-group">
     <%= f.label "Prix total : " %>
     <%= f.text_field :price, class: "total_price" %>
   </div>

   <%= link_to_remove_association "Supprimer", f %>
</div>

This is my assets/javascripts/orders.js.erb :

$(document).ready(function() {

   function getTotal(p, q) {
       var r = 0;

       if (q <= 4) {
           r = 1;
       } else if (q >= 5 && q <= 9) {
           r = 0.85;
       } else if (q >= 10 && q <= 24) {
           r = 0.75
       } else if (q >= 25 && q <= 49) {
           r = 0.65
       } else if (q >= 50 && q <= 99) {
           r = 0.55
       } else if (q >= 100 && q <= 249) {
           r = 0.45
       } else if (q >= 250 && q <= 500) {
           r = 0.40
       }

       return q * p * r;
   }

   function getUnitCost(product_name) {
       var unit_cost = 0;

       if(product_name == "Job page") {
           unit_cost = gon.jp_unit_cost
       } else if (product_name == "Job card") {
           unit_cost = gon.jc_unit_cost
       }

       return unit_cost;
   }

   $(document).on('change', '.product_name', function() {
       var q = $(".quantity").val('');
       $('.total_price').val('');

   });

   $(document).on('keyup', '.quantity', function() {
       var product_name = $(".product_name").val();
       var q = $(".quantity").val();
       var p = getUnitCost(product_name);
       var total = getTotal(p, q);
       $('.total_price').val(total)
   });

   $("#item").on('cocoon:after-insert', function(e, insertedItem) {
       var quantity = insertedItem.find('.quantity').attr('id');
       $(document).on("keyup", '#' + quantity, function() {
        var q = $("#" + quantity).val();
        var product_name = $("#" + insertedItem.find('.product_name').attr('id')).val();
        var p = getUnitCost(product_name);
        var total = getTotal(p, q);
        $("#" + insertedItem.find('.total_price').attr('id')).val(total);

    });
});

回答1:


First thing I noticed: in getUnitCost you refer to gon but I do not see how that is ever set or changed? But I assume that refers to a fixed value.

Then I see you have an cocoon:after-insert callback, but I think at that stage the quantity is always empty?

However in your change and keyup events you make the same mistake: you no longer take into account which field actually triggered the change. On change of any product-name you clear all quantities?

So for instance, when the quantity changes, you have to use that specific quantity. Now you do $('.quantity').val() which will return the value of the first quantity. So do something like

$(document).on('keyup', '.quantity', function() {
   var this = $(this);
   var parent_nested_item = this.parent('.nested-fields'); 
   var product_name = parent_nested_item.find(".product_name").val();
   var q = this.val();
   var p = getUnitCost(product_name);
   var total = getTotal(p, q);
   parent_nested_item.find('.total_price').val(total)
});

Note: this code is not tested, but an example to get you started.

In short, to recap: use the element that triggered the event ($(this)) and then use the jquery dom traversal methods to find the correct items in the correct "scope".



来源:https://stackoverflow.com/questions/44128937/how-to-get-input-value-with-cocoon-and-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!