【问题标题】:jquery clone form fields and increment idjquery克隆表单字段和增量ID
【发布时间】:2011-12-22 12:28:01
【问题描述】:

我有一个表单元素块,我想使用 jQuery 克隆方法克隆和增加它们的 ID。我尝试了许多示例,但其中很多只克隆了一个字段。

我的区块结构如下:

<div id="clonedInput1" class="clonedInput">
  <div>
    <div>
      <label for="txtCategory" class="">Learning category <span class="requiredField">*</span></label>
      <select class="" name="txtCategory[]" id="category1">
        <option value="">Please select</option>
      </select>
    </div>
   <div>
     <label for="txtSubCategory" class="">Sub-category <span class="requiredField">*</span></label>
     <select class="" name="txtSubCategory[]" id="subcategory1">
       <option value="">Please select category</option>
     </select>
   </div>
   <div>
     <label for="txtSubSubCategory">Sub-sub-category <span class="requiredField">*</span></label>
     <select name="txtSubSubCategory[]" id="subsubcategory1">
       <option value="">Please select sub-category</option>
     </select>
   </div>
</div>

显然元素排列得更好,但你明白了。

我想保留 id 结构,即 category1、subcategory1 等,因为我使用它们来动态显示基于父选择的选择选项,所以如果可以让每个克隆的块像 category1/category2/category3 等一样,那就太好了.

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    在输入中添加数据属性以获取字段名称,使用变量递增值。

    html:

    <td>
       <input type="text" data-origin="field" name="field" id="field" required="" >
      <div role="button" onclick='InsertFormRow($(this).closest("tr"),"tableID","formID");' id="addrow"> + </div>
    
    </td>
    

    并把这个javascript函数

    var rowNum = 1;

    var InsertFormRow = function(row, ptable, form)
    {
        nextrow = $(row).clone(true).insertAfter(row).prev('#' + ptable + ' tbody>tr:last');
        nextrow.attr("id", rowNum);
        nextrow.find("input").each(function() {
            this.name =  $(this).data("origin") + "_" + rowNum;
            this.id =  $(this).data("origin") + "_" + rowNum;
        });
        rowNum++;     
    }
    

    【讨论】:

      【解决方案2】:

      HTML

      <div id="clonedInput1" class="clonedInput">
          <div>
              <label for="txtCategory" class="">Learning category <span class="requiredField">*</span></label>
              <select class="" name="txtCategory[]" id="category1">
                  <option value="">Please select</option>
              </select>
          </div>
          <div>
              <label for="txtSubCategory" class="">Sub-category <span class="requiredField">*</span></label>
              <select class="" name="txtSubCategory[]" id="subcategory1">
                  <option value="">Please select category</option>
              </select>
          </div>
          <div>
              <label for="txtSubSubCategory">Sub-sub-category <span class="requiredField">*</span></label>
              <select name="txtSubSubCategory[]" id="subsubcategory1">
                  <option value="">Please select sub-category</option>
              </select>
          </div>
          <div class="actions">
              <button class="clone">Clone</button> 
              <button class="remove">Remove</button>
          </div>
      </div>
      

      JavaScript - Jquery v1.7 及更早版本

      var regex = /^(.+?)(\d+)$/i;
      var cloneIndex = $(".clonedInput").length;
      
      $("button.clone").live("click", function(){
          $(this).parents(".clonedInput").clone()
              .appendTo("body")
              .attr("id", "clonedInput" +  cloneIndex)
              .find("*").each(function() {
                  var id = this.id || "";
                  var match = id.match(regex) || [];
                  if (match.length == 3) {
                      this.id = match[1] + (cloneIndex);
                  }
          });
          cloneIndex++;
      });
      

      只有一个愚蠢的部分 :) .attr("id", "clonedInput" + $(".clonedInput").length) 但它有效 ;)

      JAvascript - JQuery 最近(支持 .on())

      var regex = /^(.+?)(\d+)$/i;
      var cloneIndex = $(".clonedInput").length;
      
      function clone(){
          $(this).parents(".clonedInput").clone()
              .appendTo("body")
              .attr("id", "clonedInput" +  cloneIndex)
              .find("*")
              .each(function() {
                  var id = this.id || "";
                  var match = id.match(regex) || [];
                  if (match.length == 3) {
                      this.id = match[1] + (cloneIndex);
                  }
              })
              .on('click', 'button.clone', clone)
              .on('click', 'button.remove', remove);
          cloneIndex++;
      }
      function remove(){
          $(this).parents(".clonedInput").remove();
      }
      $("button.clone").on("click", clone);
      
      $("button.remove").on("click", remove);
      

      工作示例here

      【讨论】:

      • 很抱歉让您感到非常痛苦。是否可以为克隆的元素添加删除按钮/链接。每个 1 个所以说如果我创建了 10 个克隆,我可以删除第五个?
      • 谢谢@Shomz 我将添加您的代码以完成示例 aboe(只是为了不引人注意)
      • 大家好,再次感谢您提供的出色代码。它的工作效率为 99.9%。有一个愚蠢的位(我认为您正在考虑 Milan Jaric 的位),如果我克隆 3 次,并删除中间(数字 2)我有 element1 和 element3。然后当我再次去克隆时,我有第二个 element3,因为 .length 认为只有 3 个。我想我可以找到一种方法来循环遍历可用元素并分配下一个可用数字,但如果你有任何建议也会很棒。
      • 嗨,干得好!当有一个选项时,我将您的脚本调整为隐藏按钮删除。见jsfiddle.net/effectlabweb/8p1e6ug5
      • 上面的正则表达式不能处理超过 9 个元素,你需要使用非贪婪匹配:/^(.+?)(\d+)$/i;(@MilanJaric,你的正则表达式也不起作用,因为它会挑出 只有最后一个整数)
      【解决方案3】:

      另一种选择是使用递归函数:

      // Accepts an element and a function
      function childRecursive(element, func){
          // Applies that function to the given element.
          func(element);
          var children = element.children();
          if (children.length > 0) {
              children.each(function (){
                  // Applies that function to all children recursively
                  childRecursive($(this), func);
              });
          }
      }
      

      然后您可以创建一个或三个函数来设置尚未克隆的表单字段的属性和值:

      // Expects format to be xxx-#[-xxxx] (e.g. item-1 or item-1-name)
      function getNewAttr(str, newNum){
          // Split on -
          var arr = str.split('-');
          // Change the 1 to wherever the incremented value is in your id
          arr[1] = newNum;
          // Smash it back together and return
          return arr.join('-');
      }
      
      // Written with Twitter Bootstrap form field structure in mind
      // Checks for id, name, and for attributes.
      function setCloneAttr(element, value){
          // Check to see if the element has an id attribute
          if (element.attr('id') !== undefined){
              // If so, increment it
              element.attr('id', getNewAttr(element.attr('id'),value));
          } else { /*If for some reason you want to handle an else, here you go*/ }
          // Do the same with name...
          if(element.attr('name') !== undefined){
              element.attr('name', getNewAttr(element.attr('name'),value));
          } else {}
          // And don't forget to show some love to your labels.
          if (element.attr('for') !== undefined){
              element.attr('for', getNewAttr(element.attr('for'),value));
          } else {}
      }
      
      // Sets an element's value to ''
      function clearCloneValues(element){
          if (element.attr('value') !== undefined){
              element.val('');
          }
      }
      

      然后添加一些标记:

      <div id="items">
          <input type="hidden" id="itemCounter" name="itemCounter" value="0">
          <div class="item">
              <div class="control-group">
                  <label class="control-label" for="item-0-name">Item Name</label>
                  <div class="controls">
                      <input type="text" name="item-0-name" id="item-0-name" class="input-large">
                  </div>
              </div><!-- .control-group-->
              <div class="control-group">
                  <label for="item-0-description" class="control-label">Item Description</label>
                  <div class="controls">
                      <input type="text" name="item-0-description" id="item-0-description" class="input-large">
                  </div>
              </div><!-- .control-group-->
          </div><!-- .item -->
      </div><!-- #items -->
      
      <input type="button" value="Add Item" id="addItem">
      

      然后你所需要的只是一些 jQuery 的优点将它们整合在一起:

      $(document).ready(function(){
          $('#addItem').click(function(){
              //increment the value of our counter
              $('#itemCounter').val(Number($('#allergyCounter').val()) + 1);
              //clone the first .item element
              var newItem = $('div.item').first().clone();
              //recursively set our id, name, and for attributes properly
              childRecursive(newItem, 
                  // Remember, the recursive function expects to be able to pass in
                  // one parameter, the element.
                  function(e){
                      setCloneAttr(e, $('#itemCounter').val());
              });
              // Clear the values recursively
              childRecursive(newItem, 
                  function(e){
                      clearCloneValues(e);
                  }
              );
              // Finally, add the new div.item to the end
              newItem.appendTo($('#items'));
          });
      });
      

      显然,如果您确切知道需要克隆和更改哪些内容,则不一定需要使用递归来获取所有内容。但是,只要它们都以正确的模式命名,这些函数允许您将它们重用于具有任意数量字段的任何大小的嵌套结构。

      有一个工作的 jsFiddle here

      【讨论】:

        【解决方案4】:

        克隆主要元素,从中删除 id 号。 在新元素中,用新的 id 号替换您希望递增的每个元素 id 中该 id 号的每个实例。

        好的,这是一个快速代码here

        基本上这部分是最重要的:

        (parseInt(/test(\d+)/.exec($(this).attr('id'))[1], 10)+1
        

        它解析当前的 id(使用 RegEx 从字符串中去除数字)并将其增加 1。在您的情况下,而不是“测试”,您应该放置“克隆输入”,并且不仅增加主要的值元素 id,但也包括内部的三个(类别、子类别和子子类别)。一旦你有了新的 ID,这应该很容易。

        希望这会有所帮助。 :)

        【讨论】:

        • 谁能拒绝提供代码 ;) 正如我所提到的,我已经尝试了很多方法,但都没有运气,所以是的,请......那太好了。
        • 你去吧,希望我说得更清楚。您还可以检查您获得的新 ID 号是否已被使用(例如,如果您克隆元素 #1,然后 #2,然后再次 #1 或 #2 - 您将获得新的 id = 3,并且自从我们克隆了 #2 以来,#3 已经存在,所以我们需要下一个增量)等等......如果您需要更多帮助,请告诉我。 :)
        猜你喜欢
        • 2021-10-19
        • 2017-09-11
        • 2015-09-28
        • 2014-12-03
        • 2013-11-03
        • 2016-09-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多