Подтвердить что ты не робот

Клонирование и переименование элементов формы с помощью jQuery

Я ищу эффективный способ клонирования/переименования или воссоздания адресных полей, чтобы предлагать возможность отправлять несколько адресов на одной странице. Итак, с примером формы следующим образом:

<div id="addresses">
  <div class="address">
    <input type="text" name="address[0].street">
    <input type="text" name="address[0].city">
    <input type="text" name="address[0].zip">
    <input type="text" name="address[0].state">
  </div>
</div>
<a href="" id="add_address">Add address form</a>

Из того, что я могу понять, есть два варианта:

  • Восстановите поле формы по полю и увеличьте индекс, который является довольно подробным:

    var index = $(".address").length;
    
    $('<`input`>').attr({
    name: 'address[' + index + '].street',
    type: 'text'
    }).appendTo(...);
    
    $('<`input`>').attr({
    name: 'address[' + index + '].city',
    type: 'text'
    }).appendTo(...);
    
    $('<`input`>').attr({
    name: 'address[' + index + '].zip',
    type: 'text'
    }).appendTo(...);
    
    $('<`input`>').attr({
    name: 'address[' + index + '].state',
    type: 'text'
    }).appendTo(...);
    
  • Клон Существующий слой и замените имя в клоне:

    $("div.address").clone().appendTo($("#addresses"));
    

Какой из них вы рекомендуете использовать с точки зрения повышения эффективности, и если его №2 вы можете предложить, как бы я пошел на поиск и заменил все вхождения [0] на [1] ([n]). Спасибо.

4b9b3361

Ответ 1

В теории простейшим способом было бы клонировать, а затем изменить имя:

var newaddress= $("#addresses div.address").eq(0).clone();
newaddress.find('input').each(function() {
    this.name= this.name.replace('[0]', '['+i+']');
});
$('#addresses').append(newaddress);

Однако:

а. jQuery clone() - это действительно неприятная работа. В IE он сериализует узлы в HTML, обрабатывает строку HTML с помощью regex (!), Чтобы удалить внутренние атрибуты идентификатора его работы, а затем просит браузер повторно проанализировать его. Это одна из моих наименее любимых частей jQuery: она сильно подвержена ошибкам, теряет некоторую информацию и работает медленно (не такая скорость имеет значение для довольно небольшой работы, которую вы, кажется, здесь делаете).

Собственный метод cloneNode(true) для браузера намного лучше, но вы не можете его использовать, если вы делаете материал jQuery, потому что он скопирует внутренние идентификаторы jQuery, что может привести к запутыванию его скриптов. Тьфу. Какой беспорядок.

б. Когда вы изменяете имя входа, будь то в input.name, как здесь, или используя attr(), как в вашем примере, в IE есть ошибки.

В частности, хотя он будет отправлять входы с правильным именем управления, они не будут индексироваться под правильным именем в form.elements HTMLCollection (или в form), хотя вы не должны использовать это в любом случае). Это не обязательно проблема, если вы выбираете входные данные на основе идентификаторов или селекторов jQuery, а не интерфейса HTMLCollection старой школы. Хуже того, что радиокнопки, если вы используете их, не будут правильно сгруппированы по именам.

Если это вас беспокоит, я боюсь использовать innerHTML/html() для создания div, как в ответе pst, это ваш единственный вариант. (Вы всегда можете комбинировать эти два, создавая с помощью HTML, затем меняя другие атрибуты и текстовый контент с помощью text(), attr(), val() и т.д., Чтобы избежать обычных проблем с экранированием HTML, когда вы идете вокруг приклеивания текстовых строк в HTML.)

Ответ 2

Это намного менее многословно, если вы напишете это здраво:-) Я бы, скорее всего, просто использовал клон и добавлял. Однако вы получите дубликаты имен. Это не имеет большого значения, если ваш back-end может корректно обрабатывать адрес []. Street ", но это может быть не так, и в таком случае вам нужно будет очистить после клонирования. Поэтому я бы рекомендовал" спрятать его в опрятной функции строителя".

function createAddress (index) {
  return jQuery(replace('\
    <div class="address">\
      <input type="text" name="address[{i}].street">\
      <input type="text" name="address[{i}].city">\
      <input type="text" name="address[{i}].zip">\
      <input type="text" name="address[{i}].state">\
    </div>\
    ', {i: index}))
}

Где замена - это некоторая аккуратная функция, которая понимает простое отображение интерполяции. Я предпочитаю "держать разметку в чем-то, что выглядит как разметка".

Беспокойство о производительности здесь, скорее всего, не оправдано.

Ответ 3

Я верю, что я переживаю то же самое и нашел отличный источник, который выглядит примерно так:

<script type="text/javascript">
    function trimNums(stringToTrim)
    {
        return stringToTrim.replace(/\d+$/,"");
    }
    function dupForm(divId, divClass, btnAdd, btnRm)
    {
    //alert(divId+'   '+divClass);
        var num     = $(divClass).length;
        var newNum  = new Number(num + 1);
        var i;
        var newElem = $('#' + divId + num).clone().attr('id', divId + newNum).fadeIn('slow');
        for (i=0; i < newElem.children().length; i++)
        {
            var attrId = trimNums(newElem.children(':eq('+i+')').attr('id'));
            var attrName = trimNums(newElem.children(':eq('+i+')').attr('name'));
            newElem.children(':eq('+i+')').attr('id', attrId + newNum).val('');
        }
        $('#' + divId + num).after(newElem);
        $('#' + btnRm).attr('disabled','');
        if (newNum == 15)
            $('#' + btnAdd).attr('disabled','disabled');
    }
    function rmForm(divId, divClass, btnAdd, btnRm)
    {
        var num = $(divClass).length;
        $('#' + divId + num).remove();
        $('#' + btnAdd).attr('disabled','');
        if (num-1 == 1)
            $('#' + btnRm).attr('disabled','disabled');
    }
</script>

и html-код:

<form id="myForm" action="testingForm.php" method="post">
<div id="input1" style="margin-bottom:4px;" class="clonedInput">
    Part #: <input name="part[]" type="text" id="part1" size="10" maxlength="15" />
    Description: <input name="description[]" type="text" id="description1" size="30" maxlength="50" />
    Qty: <input name="quantity[]" type="text" id="quantity1" size="5" maxlength="5" />

....