I have a formfield with a static row for an invoice position. With and - buttons I can add or remove additional rows for invoice positions dynamically. This works fine, but within each row I have a have a selectbox that switches the calculation method for the row (from km- to hour- or misc-based). This last feature only works for the first static row, not for the added rows?
HTML
<form action="" method="post">
<div >
<div id="position_0" >
<div >
<label for="description" >Beschreibung</label>
<textarea id="description_0" name="description_0" rows="1"></textarea>
</div>
<div >
<label for="date" >Tag der Leistung</label>
<input type="text" id="date_0" name="date_0">
</div>
<div >
<label for="amount" >Menge</label>
<input type="text" id="amount_0" name="amount_0">
</div>
<div >
<label for="type" >Abrechnungsform</label>
<select id="type_0" name="type_0">
<option value="km" selected>Kilometer</option>
<option value="hours">Stunden</option>
<option value="misc">Sonstiges</option>
</select>
</div>
<div >
<label for="price" >Einzelpreis</label>
<input type="text" id="price_0" name="price_0" value="{{price_km}}">
</div>
<div >
<label for="sum" >Summe</label>
<input type="text" id="sum_0" name="sum_0">
</div>
</div>
</div>
<div id="multiple"></div>
<button type="submit" >Speichern</button>
</form>
<button onclick="addItems()"><i ></i></button>
<button onclick="removeItems()"><i ></i></button>
Javascript/JQuery
<script>
var formatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR',
});
var km = 0.97;
var hours = 12;
var misc = 0;
// THIS DOES NOT WORK START
$("#multiple").each(function () {
var n = $(this).find("div.mb-3").length;
$('#type_' n).on('change', function () {
if (this.value === 'km') {
$('#price_' n).val(formatter.format(km));
} else if (this.value === 'hours') {
$('#price_' n).val(formatter.format(hours));
} else if (this.value === 'misc') {
$('#price_' n).val(formatter.format(misc));
}
});
});
// THIS DOES NOT WORK END
function addItems() {
$("#multiple").each(function () {
var i = $(this).find("div.col").length;
var n = (i / 6) 1;
$(this).append(`<div >
<div id="position_` n `" >
<div >
<textarea id="description_` n `" name="description_` n `" rows="1"></textarea>
</div>
<div >
<input type="text" id="date_` n `" name="date_` n `">
</div>
<div >
<input type="text" id="amount_` n `" name="amount_` n `">
</div>
<div >
<select id="type_` n `" name="type_` n `">
<option value="km" selected>Kilometer</option>
<option value="hours">Stunden</option>
<option value="misc">Sonstiges</option>
</select>
</div>
<div >
<input type="text" id="price_` n `" name="price_` n `" value="{{price_km}}">
</div>
<div >
<input type="text" id="sum_` n `" name="sum_` n `">
</div>
</div>
</div>`);
});
}
function removeItems() {
$("#multiple").each(function () {
var n = $(this).find("div.mb-3").length;
if (n != 0) {
$("#position_" n).parents("div.mb-3").remove();
}
});
}
</script>
CodePudding user response:
Only the initial items are "wired" the change
event because you run
// this line loops only on the initial items
$("#multiple").each(function () {
To solve this you have to set an .on(event)
function
// this is NOT a complete example
// 1. add a generic class to all the selects
<select id="type_0" name="type_0">
<option value="km" selected>Kilometer</option>
<option value="hours">Stunden</option>
<option value="misc">Sonstiges</option>
</select>
// 2. Set the on event, but all thing relative to the element (not fixed to the index or id
$('.mytypeselect').on('change', function () {
var self = $(this);
var row = self.closest(".row"); // find the row the select belongs at
if (self.val() === 'km') {
// find the input inside the row to change
row.find('.mypriceinput').val(formatter.format(km));
CodePudding user response:
This is not optimal, but it solves my problem
// First row of the invoice
$('select#type_0').on('change', function () {
if ($(this).val() === 'km') {
$(this).parents('div').find('#price_0').val(formatter.format(km));
} else if ($(this).val() === 'hours') {
$(this).parents('div').find('#price_0').val(formatter.format(hours));
} else if ($(this).val() === 'misc') {
$(this).parents('div').find('#price_0').val(formatter.format(misc));
}
});
// Everytime the DOM changes
$("#multiple").bind("DOMSubtreeModified", function () {
$('.mytypeselect').on('change', function () {
var sibling = $(this).parents('div');
var n = (($(this).attr('id')).split('_'))[1];
if ($(this).val() === 'km') {
sibling.find('#price_' n).val(formatter.format(km));
} else if ($(this).val() === 'hours') {
sibling.find('#price_' n).val(formatter.format(hours));
} else if ($(this).val() === 'misc') {
sibling.find('#price_' n).val(formatter.format(misc));
}
});
});