我正在开发一个表单,允许用户使用 jQuery 动态添加和删除费用行。我面临的问题是维护每行的顺序索引,即使在添加或删除行之后也是如此。
场景如下:
该表单允许用户添加多个费用行,其中每行都有描述、费用日期和金额字段。 每行的索引应该是连续的(例如,0、1、2...),并且在删除行时应该正确更新。
这是html表单
@model ExpenseApplication.Models.ViewModels.ExpenseFormViewModel
@using (Html.BeginForm("AddExpense", "Employee", FormMethod.Post))
{
<div id="expenseData" data-expense-index="@Model.Expenses.Count"></div>
<h2>Create Expense Form</h2>
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.Currency, "Currency")
@Html.DropDownListFor(m => m.Currency, Model.CurrencyList, "Select a currency--", new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Currency, "", new { @class = "text-danger" })
</div>
<h3 class="mt-3">Expenses</h3>
<table class="table">
<thead>
<tr>
<th>Description</th>
<th>Expense Date</th>
<th>Amount</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="expensesTable">
@for (int i = 0; i < Model.Expenses.Count; i++)
{
<tr>
<td>
@Html.TextBoxFor(m => m.Expenses[i].Description, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Expenses[i].Description, "", new { @class = "text-danger" })
</td>
<td>
@Html.TextBoxFor(m => m.Expenses[i].ExpenseDate, new { @class = "form-control", type = "date" })
@Html.ValidationMessageFor(m => m.Expenses[i].ExpenseDate, "", new { @class = "text-danger" })
</td>
<td>
@Html.TextBoxFor(m => m.Expenses[i].Amount, new { @class = "form-control amountInput" })
@Html.ValidationMessageFor(m => m.Expenses[i].Amount, "", new { @class = "text-danger" })
</td>
<td>
<button type="button" class="btn btn-danger removeExpense">Remove</button>
</td>
</tr>
}
</tbody>
</table>
<button type="button" id="addExpense" class="btn btn-primary">Add Expense</button>
<div>
<strong>Total Amount:</strong> <span id="totalAmount">0.00</span>
</div>
<div>
<button type="submit" class="btn btn-success" id="expenseForm">Submit Expense Form</button>
</div>
}
这是 javascript 代码
var expenseIndex = $('#expensesTable tr').length; // Initialize expenseIndex to the number of existing rows
// Add new expense row
$('#addExpense').click(function () {
var newRow = `<tr>
<td><input type="text" name="Expenses[${expenseIndex}].Description" class="form-control" /></td>
<td><input type="date" name="Expenses[${expenseIndex}].ExpenseDate" class="form-control" /></td>
<td><input type="number" name="Expenses[${expenseIndex}].Amount" class="form-control amountInput" /></td>
<td><button type="button" class="btn btn-danger removeExpense">Remove</button></td>
</tr>`;
$('#expensesTable').append(newRow);
// After adding a new row, reindex all rows
expenseIndex++
calculateTotal();
});
$(document).on('click', '.removeExpense', function () {
$(this).closest('tr').remove();
reindexExpenses();
calculateTotal();
});
function reindexExpenses() {
// Reindex each row to ensure sequential indexes
$('#expensesTable tr').each(function (index) {
$(this).find('input').each(function () {
let field = $(this).attr('name');
if (field) {
// Update the name attribute to reflect the current index
var newName = field.replace(/Expenses\[\d+\]/, `Expenses[${index}]`);
$(this).attr('name', newName);
}
});
});
// Update the expenseIndex to reflect the current number of rows
expenseIndex = $('#expensesTable tr').length;
}
// Calculate total expense amount
function calculateTotal() {
var total = 0;
$('.amountInput').each(function () {
var amount = parseFloat($(this).val()) || 0;
total += amount;
});
$('#totalAmount').text(total.toFixed(2)); // Update total amount display
}
// Update total amount on input change
$(document).on('input', '.amountInput', function () {
calculateTotal();
});
// Recalculate total on page load
$(document).ready(function () {
calculateTotal();
});
// Validate form before submission to ensure at least one expense
$('#expenseForm').click(function (e) {
var expensesCount = $('#expensesTable tr').length;
if (expensesCount === 0) {
Swal.fire({
icon: 'warning',
title: 'No Expenses Added',
text: 'At least one expense must be added.',
confirmButtonText: 'OK'
});
e.preventDefault(); // Prevent form submission if no expenses
}
});
我遇到的问题:当用户添加几行然后删除一行时,后来添加的新行无法获得正确的索引。例如,如果用户有索引为 0 和 1 的行,然后删除索引为 1 的行,则添加的新行将具有索引 2 而不是 1。
您不必在表单名称中添加索引(不是强制性的!) 如果您需要使用数据属性的编辑功能可能更有用!
另外,如果你有太多这样的需求,我可以建议移动另一个库,然后是 Jquery!
只要检查一下这个...
https://www.geeksforgeeks.org/build-an-expense-tracker-with-html-css-and-javascript/