使用jQuery动态添加行

62

我正在构建一个表单,需要多个可选输入项,现在基本上是这样的:

form example

每当用户按下加号按钮时,应向表单添加一个新的表单输入行,我该如何在jQuery中实现此操作?此外,是否可以在所有行(如果更容易/更快,则仅为最后一行)都填满时自动添加新行?这样用户就不需要按加号按钮了。

很抱歉问一个可能很基础的问题,但我对jQuery仍然非常陌生,我可以使用PHP来完成此操作,但我相信JavaScript / jQuery在这里扮演更合适的角色。


@alex:

<!DOCTYPE html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js"></script>
<script type="text/javascript">
$form = $('#personas');
$rows = $form.find('.person');

$('a#add').click(function() {
    $rows.find(':first').clone().insertAfter($rows.find(':last'));
    $justInserted = $rows.find(':last');
    $justInserted.hide();
    $justInserted.find('input').val(''); // it may copy values from first one
    $justInserted.slideDown(500);
});
</script>
</head>

<body>
<form id="personas" name="personas" method="post" action="">
  <table width="300" border="1" cellspacing="0" cellpadding="2">
    <tr>
      <td>Name</td>
      <td>More?</td>
    </tr>
    <tr class="person">
      <td><input type="text" name="name[]" id="name[]" /></td>
      <td><a href="#" id="add">+</a></td>
    </tr>
  </table>
</form>
</body>
</html>

@Rippo:我试过了,不起作用。$form.find('.person') 不是应该找到在具有 personas id 的表单内拥有 person 类的所有元素吗? - Alix Axel
为什么要使用选择器a#add,而不是仅仅使用#add? - goat
@chris:我明白,我只是试图不改变@alex的逻辑。 - Alix Axel
@Alix Axel - 你搞定了吗?因为我正在寻找类似的东西。 - Hacker
@pradeep:是的,否则我不会接受这个答案。 - Alix Axel
5个回答

65

这会让你接近目标,添加按钮已从表格中移除,所以你可能需要考虑这一点...

<script type="text/javascript">
    $(document).ready(function() {
        $("#add").click(function() {
          $('#mytable tbody>tr:last').clone(true).insertAfter('#mytable tbody>tr:last');
          return false;
        });
    });
</script>

HTML标记看起来像这样

  <a  id="add">+</a></td>
  <table id="mytable" width="300" border="1" cellspacing="0" cellpadding="2">
  <tbody>
    <tr>
      <td>Name</td>
    </tr>
    <tr class="person">
      <td><input type="text" name="name" id="name" /></td>
    </tr>
    </tbody>
  </table>

编辑:如果要在插入后清空文本框中的值...

    $('#mytable tbody>tr:last').clone(true).insertAfter('#mytable tbody>tr:last');
    $('#mytable tbody>tr:last #name').val('');
    return false;

编辑2 无法自拔,要重置插入的TR中的所有下拉列表,请执行以下操作

$("#mytable tbody>tr:last").each(function() {this.reset();});           

其余的就留给你了!


1
可以,很好用。现在,是否有任何方法可以将新创建的行中的所有输入/选择/文本区域等重置为其原始状态? - Alix Axel
非常好的解决方案,对我非常有效。我通过在“insertAfter()”之后但分号之前添加以下内容使我的淡入:.hide().fadeIn(500) - Sean Reifschneider
此外,您的HTML代码片段中不包含“add”按钮。这意味着您正在使用“.add”而不是“#add”,但这是我使用的代码: <td><img src="add.png" class="add" alt="+"></img></td> - Sean Reifschneider
我认为在主表格之外建立一个默认的行,并根据需要进行克隆可能更有意义。这将使得针对每个字段"重置"个别默认值变得更加容易,对吗?否则,非常好的答案。谢谢!我的便捷小插件启动了。 - Chief Alchemist
我只是想说,在2018年2月4日,这个答案对我仍然有帮助。感谢您提供了一个清晰、详细的答案和示例。 - Dan Hoover
显示剩余2条评论

7
作为对上面答案的补充:您可能需要更改输入元素的名称/ID中的ID(请注意,字段名称中不应该有数字):
<input name="someStuff.entry[2].fieldOne" id="someStuff_fdf_fieldOne_2" ..>

我已经做了一些全局变量,默认设置为0:

var globalNewIndex = 0;

在将新行克隆并重置值后,在添加函数中:

                var newIndex = globalNewIndex+1;
                var changeIds = function(i, val) {
                    return val.replace(globalNewIndex,newIndex);
                }
                $('#mytable tbody>tr:last input').attr('name', changeIds ).attr('id', changeIds );
                globalNewIndex++;

4
我尝试过类似这样的方法,它能正常工作;
这是HTML部分: enter image description here
<table class="dd" width="100%" id="data">
<tr>
<td>Year</td>
<td>:</td>
<td><select name="year1" id="year1" >
<option value="2012">2012</option>
<option value="2011">2011</option>
</select></td>
<td>Month</td>
<td>:</td>
<td width="17%"><select name="month1" id="month1">
  <option value="1">January</option>
  <option value="2">February</option>
  <option value="3">March</option>
  <option value="4">April</option>
  <option value="5">May</option>
  <option value="6">June</option>
  <option value="7">July</option>
  <option value="8">August</option>
  <option value="9">September</option>
  <option value="10">October</option>
  <option value="11">November</option>
  <option value="12">December</option>
</select></td>
<td width="7%">Week</td>
<td width="3%">:</td>
<td width="17%"><select name="week1" id="week1" >
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
</select></td>
<td width="8%">&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>Actual</td>
<td>:</td>
<td width="17%"><input name="actual1" id="actual1" type="text" /></td>
<td width="7%">Max</td>
<td width="3%">:</td>
<td><input name="max1" id="max1" type="text" /></td>
<td>Target</td>
<td>:</td>
<td><input name="target1" id="target1" type="text" /></td>
</tr>

这是JavaScript的部分;
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type='text/javascript'>
//<![CDATA[
$(document).ready(function() {
var currentItem = 1;
$('#addnew').click(function(){
currentItem++;
$('#items').val(currentItem);
var strToAdd = '<tr><td>Year</td><td>:</td><td><select name="year'+currentItem+'" id="year'+currentItem+'" ><option value="2012">2012</option><option value="2011">2011</option></select></td><td>Month</td><td>:</td><td width="17%"><select name="month'+currentItem+'" id="month'+currentItem+'"><option value="1">January</option><option value="2">February</option><option value="3">March</option><option value="4">April</option><option value="5">May</option><option value="6">June</option><option value="7">July</option><option value="8">August</option><option value="9">September</option><option value="10">October</option><option value="11">November</option><option value="12">December</option></select></td><td width="7%">Week</td><td width="3%">:</td><td width="17%"><select name="week'+currentItem+'" id="week'+currentItem+'" ><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option></select></td><td width="8%"></td><td colspan="2"></td></tr><tr><td>Actual</td><td>:</td><td width="17%"><input name="actual'+currentItem+'" id="actual'+currentItem+'" type="text" /></td><td width="7%">Max</td> <td width="3%">:</td><td><input name="max'+currentItem+'" id ="max'+currentItem+'"type="text" /></td><td>Target</td><td>:</td><td><input name="target'+currentItem+'" id="target'+currentItem+'" type="text" /></td></tr>';
  $('#data').append(strToAdd);

 });
 });

 //]]>
 </script>

最后是 PHP 提交部分:

    for( $i = 1; $i <= $count; $i++ )
{
    $year = $_POST['year'.$i];
    $month = $_POST['month'.$i];
    $week = $_POST['week'.$i];
    $actual = $_POST['actual'.$i];
    $max = $_POST['max'.$i];
    $target = $_POST['target'.$i];
    $extreme = $_POST['extreme'.$i];
    $que = "insert INTO table_name(id,year,month,week,actual,max,target) VALUES ('".$_POST['type']."','".$year."','".$month."','".$week."','".$actual."','".$max."','".$target."')";
    mysql_query($que);

}

您可以通过动态表格行插入器查找更多详细信息。


1
谨慎使用 PHP 部分,因为它容易受到 SQL 注入攻击(我想)。 - Rippo

3

未经测试。请进行修改以适合您的需求:

$form = $('#my-form');

$rows = $form.find('.person-input-row');

$('button#add-new').click(function() {

    $rows.find(':first').clone().insertAfter($rows.find(':last'));

    $justInserted = $rows.find(':last');
    $justInserted.hide();
    $justInserted.find('input').val(''); // it may copy values from first one
    $justInserted.slideDown(500);


});

使用这种方法比复制innerHTML更好,因为您将丢失所有附加的事件等。


谢谢,那很有道理,但我仍然无法让它工作,请检查我的编辑后的问题。 - Alix Axel
这将克隆 tr 中的内容,也就是 td,并将其插入到最后一个 td 后面。接近正确,但还不完全正确。 - Rippo
一切都挺好的,直到编辑部分 :) 抱歉,我发布后出门了,没机会进行编辑。 - alex

0

在其他答案的基础上,我稍微简化了一下。通过克隆最后一个元素,我们可以免费获得“添加新”按钮(由于克隆,您必须将ID更改为类),并且还可以减少DOM操作。我不得不使用filter()而不是find()来获取最后一个元素。

$('.js-addNew').on('click', function(e) {
   e.preventDefault();
   var $rows   = $('.person'),
       $last   = $rows.filter(':last'),
       $newRow = $last.clone().insertAfter($last);

   $last.find($('.js-addNew')).remove(); // remove old button
   $newRow.hide().find('input').val('');
   $newRow.slideDown(500);
});

这个可以工作,但是因为在注册事件处理程序时任何新行上的按钮都不存在,所以你需要再次这样做。 - jhmckimm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接