点击destroy with cocoon后,如何在没有销毁记录的情况下重新计算发票
After clicking on destroy with cocoon, how to recalculate invoice without destroyed record
上下文
我正在使用 cocoon gem 为 invoice
创建嵌套的 invoice_rows
。一切都按预期工作(删除、创建嵌套记录等)。
在 invoice form
中,我也在跟踪最实际的 total_invoice amount
和 Javascript。使用我的 Javascript 代码,我可以在 price, quantity or VAT
更改时或使用 cocoon 创建新的 invoice_row
时重新计算 total_invoice amount
。
问题
当我删除嵌套记录时会出现此问题。按照文档,我尝试使用 cocoon:after-remove
来触发事件,但是在我删除 invoice_row
后没有任何东西被触发。
其他尝试
我还尝试了删除按钮上的单击事件(另请参阅脚本中注释掉的代码)。不幸的是,删除的嵌套记录的 class 仍然被我的 Javascript 代码提取,因此被输入到 total_invoice amount
的计算中。 (因此我猜 cocoon:after-remove
命令)
代码
invoice_form.html.erb
<div class="form-container col col-sm-6 col-lg-12">
<%= simple_form_for [@hotel, @invoice] do |f|%>
<h5><strong><u><%= t('.invoice') %> </u></strong></h5>
<!-- headers -->
<div class="row">
<div class="col col-sm-3"><b>description</b></div>
<div class="col col-sm-2"><b>unit price</b></div>
<div class="col col-sm-2"><b>amount</b></div>
<div class="col col-sm-2"><b>VAT (%)</b></div>
<div class="col col-sm-2"><b>Total</b></div>
</div>
<div class="border-invoice"></div>
<!-- headers -->
<%= f.simple_fields_for :invoice_rows do |invoice_row| %>
<div class="reservation-details">
<%= render 'invoice_row_fields', f: invoice_row %>
</div>
<% end %>
<div id="check">
<%= link_to_add_association f, :invoice_rows do %>
<div class="option-add-option-price">
<div class="prices-border">
<i class="fas fa-plus"></i> Add another invoice line
</div>
</div>
<% end %>
</div>
<div class="border-invoice"></div>
<div class="row">
<div class="col-sm-8"></div>
<div class="col-sm-1"><b>Subtotal</b></div>
<div class="col col-sm-2"><input type="text" class="field nettotal form-control"></div>
</div>
<br>
<div class="row">
<div class="col-sm-8"></div>
<div class="col-sm-1">VAT</div>
<div class="col col-sm-2"><input type="text" class="field vat-total form-control"></div>
</div>
<br>
<div class="row">
<div class="col-sm-8"></div>
<div class="col-sm-1"><b>Total</b></div>
<div class="col col-sm-2"><input type="text" class="field gross-total form-control"></div>
</div>
<div class="row">
<div class="col col-sm-6"> <%= f.button :submit, t(".invoice_button"), class: "create-reservation-btn"%>
</div>
</div>
<% end %>
</div>
发票表格脚本
// $(document).on('click', '.delete-vat', function() { /* recalculate */
$(document).ready(function(){
$('#check')
.on('cocoon:after-remove', function() { /* recalculate */
var result = 0
var vat_result = 0
var price = [];
var quantity = [];
var vat = [];
console.log('yes')
$('.price').each(function(i, obj) {
price.push((Math.round(+obj.value*100)/100).toFixed(2));
});
$('.quantity').each(function(i, obj) {
quantity.push(+obj.value);
});
$('.vat').each(function(i, obj) {
vat.push(+obj.value);
});
var result = 0
price.forEach((o,i)=>{
$(".gross-total").eq( i ).val(o*quantity[i]);
result += o*quantity[i];
// console.log(result)
$(".gross-total").val(result);
});
var vat_result = 0
price.forEach((o,i)=>{
$(".vat-total").eq( i ).val(o*vat[i]);
vat_result += o*vat[i]/100 * quantity[i];
$(".vat-total").val(vat_result);
});
var sub = result - vat_result
$(".nettotal").val(sub);
})
_invoice_row_fields.html.erb
<div class="nested-fields">
<div class="row test">
<div class="col col-sm-3"><%= f.input :description, placeholder: "Product or service description", label: false %></div>
<div class="col col-sm-2"><%= f.input :price, placeholder: "Price incl. VAT", label: false, input_html:{class: "field price"} %></div>
<div class="col col-sm-2 "><%= f.input :amount, label: false, input_html:{class: "field quantity"} %></div>
<div class="col col-sm-2"><%= f.collection_select :vat_percentage, @hotel.vat_groups, :vat_percentage, :vat_percentage, {prompt: "Select a VAT"}, {class: "form-control vat"} %></div>
<div class="col col-sm-2"><input type="text" class="field subtotal form-control"></div>
<div class="col col-sm-1">
<%= link_to_remove_association f do %>
<i class="fas fa-trash delete-vat"></i>
<% end %>
</div>
</div>
</div>
使用茧移除物品时,它们通常不会真正移除,只是隐藏。这是因为表单(和所有更改)仅在将表单发布到服务器时才会保存。
因此,如果您添加了一个嵌套项,但没有保存表单,然后将其删除,则它会从表单中物理删除 (DOM)。但是,如果删除了一次保存的嵌套项目,则需要将其隐藏,并设置 _destroy
标志,以便服务器 知道 要删除哪些项目。
所以在您的 javascript 中正确处理这个,您可以使用 :visible
选择器。例如。做类似
的事情
$('.price:visible').each(function() { ...
此外,您的 cocoon:after-remove
现在已在 #check
div 上注册?您应该在嵌套项目的周围 div 上注册它,例如form
本身会更好用恕我直言。
上下文
我正在使用 cocoon gem 为 invoice
创建嵌套的 invoice_rows
。一切都按预期工作(删除、创建嵌套记录等)。
在 invoice form
中,我也在跟踪最实际的 total_invoice amount
和 Javascript。使用我的 Javascript 代码,我可以在 price, quantity or VAT
更改时或使用 cocoon 创建新的 invoice_row
时重新计算 total_invoice amount
。
问题
当我删除嵌套记录时会出现此问题。按照文档,我尝试使用 cocoon:after-remove
来触发事件,但是在我删除 invoice_row
后没有任何东西被触发。
其他尝试
我还尝试了删除按钮上的单击事件(另请参阅脚本中注释掉的代码)。不幸的是,删除的嵌套记录的 class 仍然被我的 Javascript 代码提取,因此被输入到 total_invoice amount
的计算中。 (因此我猜 cocoon:after-remove
命令)
代码
invoice_form.html.erb
<div class="form-container col col-sm-6 col-lg-12">
<%= simple_form_for [@hotel, @invoice] do |f|%>
<h5><strong><u><%= t('.invoice') %> </u></strong></h5>
<!-- headers -->
<div class="row">
<div class="col col-sm-3"><b>description</b></div>
<div class="col col-sm-2"><b>unit price</b></div>
<div class="col col-sm-2"><b>amount</b></div>
<div class="col col-sm-2"><b>VAT (%)</b></div>
<div class="col col-sm-2"><b>Total</b></div>
</div>
<div class="border-invoice"></div>
<!-- headers -->
<%= f.simple_fields_for :invoice_rows do |invoice_row| %>
<div class="reservation-details">
<%= render 'invoice_row_fields', f: invoice_row %>
</div>
<% end %>
<div id="check">
<%= link_to_add_association f, :invoice_rows do %>
<div class="option-add-option-price">
<div class="prices-border">
<i class="fas fa-plus"></i> Add another invoice line
</div>
</div>
<% end %>
</div>
<div class="border-invoice"></div>
<div class="row">
<div class="col-sm-8"></div>
<div class="col-sm-1"><b>Subtotal</b></div>
<div class="col col-sm-2"><input type="text" class="field nettotal form-control"></div>
</div>
<br>
<div class="row">
<div class="col-sm-8"></div>
<div class="col-sm-1">VAT</div>
<div class="col col-sm-2"><input type="text" class="field vat-total form-control"></div>
</div>
<br>
<div class="row">
<div class="col-sm-8"></div>
<div class="col-sm-1"><b>Total</b></div>
<div class="col col-sm-2"><input type="text" class="field gross-total form-control"></div>
</div>
<div class="row">
<div class="col col-sm-6"> <%= f.button :submit, t(".invoice_button"), class: "create-reservation-btn"%>
</div>
</div>
<% end %>
</div>
发票表格脚本
// $(document).on('click', '.delete-vat', function() { /* recalculate */
$(document).ready(function(){
$('#check')
.on('cocoon:after-remove', function() { /* recalculate */
var result = 0
var vat_result = 0
var price = [];
var quantity = [];
var vat = [];
console.log('yes')
$('.price').each(function(i, obj) {
price.push((Math.round(+obj.value*100)/100).toFixed(2));
});
$('.quantity').each(function(i, obj) {
quantity.push(+obj.value);
});
$('.vat').each(function(i, obj) {
vat.push(+obj.value);
});
var result = 0
price.forEach((o,i)=>{
$(".gross-total").eq( i ).val(o*quantity[i]);
result += o*quantity[i];
// console.log(result)
$(".gross-total").val(result);
});
var vat_result = 0
price.forEach((o,i)=>{
$(".vat-total").eq( i ).val(o*vat[i]);
vat_result += o*vat[i]/100 * quantity[i];
$(".vat-total").val(vat_result);
});
var sub = result - vat_result
$(".nettotal").val(sub);
})
_invoice_row_fields.html.erb
<div class="nested-fields">
<div class="row test">
<div class="col col-sm-3"><%= f.input :description, placeholder: "Product or service description", label: false %></div>
<div class="col col-sm-2"><%= f.input :price, placeholder: "Price incl. VAT", label: false, input_html:{class: "field price"} %></div>
<div class="col col-sm-2 "><%= f.input :amount, label: false, input_html:{class: "field quantity"} %></div>
<div class="col col-sm-2"><%= f.collection_select :vat_percentage, @hotel.vat_groups, :vat_percentage, :vat_percentage, {prompt: "Select a VAT"}, {class: "form-control vat"} %></div>
<div class="col col-sm-2"><input type="text" class="field subtotal form-control"></div>
<div class="col col-sm-1">
<%= link_to_remove_association f do %>
<i class="fas fa-trash delete-vat"></i>
<% end %>
</div>
</div>
</div>
使用茧移除物品时,它们通常不会真正移除,只是隐藏。这是因为表单(和所有更改)仅在将表单发布到服务器时才会保存。
因此,如果您添加了一个嵌套项,但没有保存表单,然后将其删除,则它会从表单中物理删除 (DOM)。但是,如果删除了一次保存的嵌套项目,则需要将其隐藏,并设置 _destroy
标志,以便服务器 知道 要删除哪些项目。
所以在您的 javascript 中正确处理这个,您可以使用 :visible
选择器。例如。做类似
$('.price:visible').each(function() { ...
此外,您的 cocoon:after-remove
现在已在 #check
div 上注册?您应该在嵌套项目的周围 div 上注册它,例如form
本身会更好用恕我直言。