I am using Stimulus Nested Forms to dynamically create line items for an invoice system. When I click remove to remove a row I need to somehow run my total function to update the total and remove whatever total was in the deleted row. I’m not sure how to do that exactly with this component. Stimulus Rails Nested Form | Stimulus Components
Here is the item fields partial. When I click the remove row I also need to run the settotal function.Any ideas?
<div class="nested-form-wrapper" data-new-record="<%= form.object.new_record? %>">
<div data-controller="total">
<div class="row">
<div class="form-group col-md-3">
<%= form.label :name, 'Name', class: "form-label" %>
<%= form.text_field :name, class: "form-control" %>
</div>
<div class="form-group col-md-3">
<%= form.label :description, 'Description', class: 'form-label' %>
<%= form.text_field :description, class: "form-control" %>
</div>
<div class="form-group col-md-1">
<%= form.label :qty, 'Quantity', class: "form-label" %>
<%= form.text_field :qty, class: 'form-control', data: {action: 'change->total#settotal', 'total-target': 'qty'} %>
</div>
<div class="form-group col-md-2">
<%= form.label :cost, 'Price', class: "form-label" %>
<%= form.text_field :cost, class: 'form-control', data: {action: 'change->total#settotal', 'total-target': 'cost'} %>
</div>
<div class="form-group col-md-2">
<%= form.label :total, 'Total', class: "form-label" %>
<input type="text" data-total-target="total" class= "form-control" name="total" id="total" value="0.0" readonly="true">
</div>
<div class="form-group col-md-1">
<label class="form-label"> </label>
<%= link_to "Remove", "#", data: { action: "click->nested-form#remove"}, class: "form-control btn btn-sm btn-danger" %>
<%= form.hidden_field :_destroy %>
</div>
</div>
</div>
</div>
Here is some more info: I think I found the controller section where the remove happens. And below that is my total controller. I need to update the totals on the screen when a row with pricing is deleted.
class src_default extends Controller {
add(e) {
e.preventDefault();
const content = this.templateTarget.innerHTML.replace(/NEW_RECORD/g, new Date().getTime().toString());
this.targetTarget.insertAdjacentHTML("beforebegin", content);
}
remove(e) {
e.preventDefault();
const wrapper = e.target.closest(this.wrapperSelectorValue);
if (wrapper.dataset.newRecord === "true") {
wrapper.remove();
} else {
wrapper.style.display = "none";
const input = wrapper.querySelector("input[name*='_destroy']");
input.value = "1";
}
}
}
total_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "qty", "cost", "total" ]
connect() {
this.settotal()
}
settotal() {
this.totalTarget.value = Number(this.qtyTarget.value * this.costTarget.value).toFixed(2)
var arr = document.getElementsByName('total');
var tot=0;
var totf=0;
for(var i=0;i<arr.length;i++){
if(parseFloat(arr[i].value))
tot += parseFloat(arr[i].value);
totf = (Math.round(tot * 100) / 100).toFixed(2);
}
document.getElementById('invoice_net_amount').value = totf;
}
}