克隆<tr>并将<td>内元素的name属性增加1

7

我将要在表单中实现“新增行”功能。该表单的结构类似于:

<table>
<tr>
     <td><input type="text" name="v1[label]" /></td>
     <td><input type="text" name="v1[observation]" /></td>
     <td><input type="text" name="v1[remarks]" /></td>
</tr>
<tr>
     <td><input type="text" name="v2[label]" /></td>
     <td><input type="text" name="v2[observation]" /></td>
     <td><input type="text" name="v2[remarks]" /></td>
</tr>
<tr>
    <td colspan="3">
       <input type="button" id="addrow" value="Add One More Row">&nbsp;
       <input type="submit" name="proceed" value="Submit" />
    </td> 
</tr>
</table>

如图所示,随着每一行的增加,v []数字也会增加。v1、v2等等。

我想要的是什么

当单击“添加一行”按钮时,应发生以下事情:

  • 在最后一行(带有按钮的行)上方插入新行
  • 该行中的名称属性值增加1(即v2 [label]变为v3 [label],v2 [observation]变为v3 [observation]等)

我尝试过的方法

我最接近的方法是使用jQuery的clone()。这确实完美地添加了该行。但我很难找到一种方法,以便每次单击按钮时都可以将名称属性的值增加1。

目前正在使用的jQUERY

$('input:button[id="addrow"]').click(function(){

   var secondlast = $('table tr:last').prev('tr');
   secondlast.clone().insertBefore(secondlast);

});

如果我点击按钮两次,将添加以下HTML内容。
<tr>
     <td><input type="text" name="v2[label]" /></td>
     <td><input type="text" name="v2[observation]" /></td>
     <td><input type="text" name="v2[remarks]" /></td>
</tr>

<tr>
     <td><input type="text" name="v2[label]" /></td>
     <td><input type="text" name="v2[observation]" /></td>
     <td><input type="text" name="v2[remarks]" /></td>
</tr>

现在正在添加一行,但是第三行和第四行的name属性应该分别为v3和v4,而仍然保留为v2。我知道clone()无法做到这一点,因此我正在寻找替代方法。


你尝试过在插入之前处理克隆吗?例如使用 secondlast.clone().each('input'),解析名称并替换数字。 - Eregrith
嗯,那很有道理。我会尝试看看能否实现。 - asprin
@Eregrith 我对逻辑非常清楚,但是很难将其转换为编程语法 :( - asprin
您可以直接操作属性,并根据事件发生时表格行数的数量进行递增。 - Alex Gill
2个回答

6
$('input:button[id="addrow"]').click(function(){
    var secondlast = $('table tr:last').prev('tr');
    var newClone = secondlast.clone();
    // find all the inputs within your new clone and for each one of those
    newClone.find('input').each(function() {
        var currentNameAttr = $(this).attr('name'); // get the current name attribute
        // construct a new name attribute using regular expressions
        // the match is divided into three groups (indicated by parentheses)
        // p1 will be 'v', p2 will be the number, p3 will be the remainder of the string
        var newNameAttr = currentNameAttr.replace(/^(v)(\d+)(.*)$/, function(match, p1, p2, p3) {
            return p1+(parseInt(p2)+1)+p3;
        });
        $(this).attr('name', newNameAttr);   // set the incremented name attribute 
    });
    // insert after is I assume what you want
    newClone.insertAfter(secondlast);
});

编辑

// you could also simply increment any digit you find as Batman indicated
var newNameAttr = currentNameAttr.replace(/\d+/, function(match) {
    return (parseInt(match)+1);
});

这个按预期工作。给我一点时间来试试玩。我还要用选择框测试它。 - asprin
没错。按预期完美工作。我只是用newClone.find('input, select').each(function() 替换了 newClone.find('input').each(function()。+1 并接受为答案。还感谢你提供代码的注释 xD - asprin
2
这是一个非常优雅的解决方案,但有一个巨大的警告:在jQuery中克隆输入元素并更改name属性在IE6/7中不起作用。链接 - chridam
@chridam 谢谢,我不知道IE6/7不允许您动态更新名称属性。 - cbayram
@cbayram 不用担心。如果($.browser.msie === true)成为真正的问题,我想OP可以添加mergeAttributes修复。 - chridam

0
如果您需要将这些输入中的数据发送到服务器,那么确定需要取多少个v* 将会很困难... 相反,我建议您使用[] 在数组中添加行。
您的HTML代码应该如下所示:
<table>
<tr>
     <td><input type="text" name="v[label][]" /></td>
     <td><input type="text" name="v[observation][]" /></td>
     <td><input type="text" name="v[remarks][]" /></td>
</tr>
<tr>
     <td><input type="text" name="v[label][]" /></td>
     <td><input type="text" name="v[observation][]" /></td>
     <td><input type="text" name="v[remarks][]" /></td>
</tr>
<tr>
    <td colspan="3">
       <input type="button" id="addrow" value="Add One More Row">&nbsp;
       <input type="submit" name="proceed" value="Submit" />
    </td> 
</tr>
</table>

POST变量将是唯一的:v,很容易通过循环来获取数据,这里是一个PHP示例。

foreach($_POST['v']['label'] as $k=>$v){
    $_POST['v']['label'][$k]; // label
    $_POST['v']['observation'][$k]; // label
    $_POST['v']['remarks'][$k]; // label
}

这样可以允许无限数量的输入,无需为每个克隆处理和重新格式化名称,并且更易于使用。


实际上,我想每次将值增加1的原因是因为我希望以您列出的类似方式处理表单。如果没有其他选择,我会将其保留为最后一个选项。 - asprin

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