#javascript #html #jquery #function
#javascript #HTML #jquery #функция
Вопрос:
У меня есть форма, которая показывает выпадающее меню и текстовое поле рядом с ним:
<html>
<body>
<table>
<tbody class="project_wrapper">
<tr>
<td scope="row">
<select id="test_project" name="test_project[]">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input id="test_value" name="test_value[]" type="text" placeholder="Enter value"></td>
<td><div id="test_calc"></div></td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="3">
<a href="javascript:void(0);" class="add_project" title="Add project">Add another project</a>
</td>
</tr>
</tbody>
</table>
</body>
</html>
Вы можете выбрать одно из значений в раскрывающемся списке, и когда вы вводите числовое значение в текстовое поле, при каждом нажатии клавиши будет отображаться значение, умноженное на выбранное значение. Вы также можете нажать на ссылку «Добавить другой проект», и она добавит / создаст другой раскрывающийся список и текстовое поле. Это уже работает и выполняется с помощью следующего кода Jquery:
<script type="text/javascript">
$(document).ready(function(){
var addProject = $('.add_project');
var wrapper = $('.project_wrapper');
var projectHTML = `<tr>
<td scope="row">
<select id="test_project2" name="test_project[]" class="custom-select">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input id="test_value2" name="test_value[]" type="text" placeholder="Enter value"></td>
<td><div id="test_calc2"></div></td>
</tr>`;
$(addProject).click(function(){
$(wrapper).append(projectHTML);
});
});
$('#test_value').keyup(function(){
$('#test_calc').text(Math.round($(this).val() * $("#test_project option:selected").val()));
});
Проблема в том, что я не могу заставить функцию умножения работать / отображать результат для любых вновь добавленных строк. Выше вы можете видеть, что я попытался жестко закодировать значения test_value2
и test_calc2
, а затем добавил это ниже:
$('#test_value2').keyup(function(){
$('#test_calc2').text(Math.round($(this).val() * $("#test_project2 option:selected").val()));
});
Я бы ожидал, что результат (по крайней мере, для одной новой добавленной строки) будет отображаться так же, как и для первой строки, но, похоже, ничего не происходит. Моя цель — получить результаты для добавленной строки, а затем также найти способ заставить эту функцию вычисления ввода работать для любого количества добавленных строк (а не жестко закодированных значений 2, 3, 4 и т.д.).
ids
Я думаю, что их нужно будет динамически назначать по мере добавления строк, а затем name
они останутся неизменными для хранения массивов для test_array
и test_value
, которые я собираюсь получать и обрабатывать через PHP.
Спасибо!
Комментарии:
1. Что это за ввод
type="type"
? Вы имеете в видуtype="number"
?2. @RokoC. Булджан упс, спасибо, я набирал это слишком быстро и имел в виду «текст», но просто дважды набрал «тип». Это определенно может быть и «число», поскольку я ожидаю чисел, но я не хочу показывать стрелки, которые появляются в текстовом поле.
Ответ №1:
- Удалите все свои идентификаторы из строк шаблона, используйте классы или
name=""
вместо этого в качестве селекторов - Присвойте идентификатор вашему TBODY, мы будем использовать его в качестве делегатора
.on()
событий - Используйте
"input"
событие, а не"keydown"
событие. Вы также можете копировать / вставлять значения, помните? - на
"input"
— обратитесь к родительскому TR с помощью.closest()
перед спуском назад (с помощью.find()
), чтобы найти элементы, характерные для этой строки - Используйте
parseInt()
илиparseFloat()
для обработки входных строк. Также не забывайте всегда возвращаться к числу, т.е.0
для предотвращенияNaN
результатов
jQuery(function($) {
const projectHTML = `<tr>
<td>
<select name="test_project[]" class="custom-select">
<option value="" selected>Select</option>
<option value="10">10</option>
<option value="20">20</option>
</select>
</td>
<td><input name="test_value[]" type="type" placeholder="Enter value"></td>
<td><div class="result"></div></td>
</tr>`;
const $projects = $("#projects"); // assign an ID to your tbody
const $addProject = $('.add_project');
const arrRow = () => $projects.append(projectHTML);
// Create new row on click
$addProject.on("click", arrRow);
// Add the first row
arrRow();
// use a delegator which is not dymanic (the TBODY in this case),
// and use delegated events to any ":input" element:
$projects.on("input", ":input", function(ev) {
const $tr = $(this).closest("tr");
const $project = $tr.find('[name="test_project[]"]');
const $value = $tr.find('[name="test_value[]"]');
const $result = $tr.find(".result");
const project = parseInt($project.val(), 10) || 0;
const value = parseFloat($value.val()) || 0;
const result = project * value;
$result.text(result);
});
});
<table>
<tbody id="projects"></tbody>
<tbody>
<tr>
<td colspan="3">
<a href="javascript:void(0);" class="add_project" title="Add project">Add another project</a>
</td>
</tr>
</tbody>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Комментарии:
1. Это отлично, спасибо! Во-первых, для решения проблемы, а затем также советы и причины для них были очень полезны для улучшения моих знаний и навыков. Мне особенно нравится, как вы очистили мой HTML, чтобы выпадающее меню и текстовое поле не дублировались.
Ответ №2:
Идентификаторы должны быть уникальными, вместо этого всякий раз, когда вы добавляете другую строку, вы дублируете идентификаторы.
Вместо идентификаторов я изменил их на class, чтобы объединить это ключевое слово с .closest() и .find(), чтобы получить интересующие значения.
Более того, поскольку вы добавляете новые элементы в таблицу, вам нужно делегировать событие.
Если вы измените выбор, вам нужно будет вычислить снова, а не только при вводе в поле ввода.
var addProject = $('.add_project');
var wrapper = $('.project_wrapper');
var projectHTML = '<tr>
<td scope="row">
<select class="test_project" name="test_project[]" class="custom-select">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input class="test_value" name="test_value[]" type="number" placeholder="Enter value"></td>
<td><div class="test_calc"></div></td>
</tr>';
$(addProject).click(function () {
$(wrapper).append(projectHTML);
});
$(document).on('input', '.test_value', function (e) {
$(this).closest('tr').find('.test_calc').text(Math.round($(this).val() * $(this).closest('tr').find('.test_project option:selected').val() || 0));
});
$(document).on('change', '.test_project', function(e) {
$(this).closest('tr').find('.test_value').trigger('input');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody class="project_wrapper">
<tr>
<td scope="row">
<select class="test_project" name="test_project[]">
<option selected>Select</option>
<option>10</option>
<option>20</option>
</select>
</td>
<td><input class="test_value" name="test_value[]" type="number" placeholder="Enter value"></td>
<td>
<div class="test_calc"></div>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="3">
<a href="javascript:void(0);" class="add_project" title="Add project">Add another project</a>
</td>
</tr>
</tbody>
</table>
Комментарии:
1. Также спасибо за ваш отличный ответ! И я ценю, что вы предоставляете ссылки на соответствующие концепции.