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

Лучший способ добавить дополнительную (вложенную) форму в середине формы с вкладками

У меня есть веб-приложение, состоящее в основном из большой формы с информацией. Форма разбивается на несколько вкладок, чтобы сделать ее более читаемой для пользователя:

<form>
<div id="tabs">
  <ul>
    <li><a href="#tab1">Tab1</a></li>
    <li><a href="#tab2">Tab2</a></li>
  </ul>
  <div id="tab1">A big table with a lot of input rows</div>
  <div id="tab2">A big table with a lot of input rows</div>
</div>
</form>

Форма динамически расширяется (дополнительные строки добавляются в таблицы). Каждые 10 секунд форма сериализуется и синхронизируется с сервером.

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

Быстрый эскиз такой страницы будет выглядеть так:

<form action="bigform.php">
<div id="tabs">
  <ul>
    <li><a href="#tab1">Tab1</a></li>
    <li><a href="#tab2">Tab2</a></li>
  </ul>
  <div id="tab1">A big table with a lot of input rows</div>
  <div id="tab2">
    <div class="associatedinfo">
    <p>Information for Joe</p>
    <ul>
      <li><input name="associated[26][]" /></li>
      <li><input name="associated[26][]" /></li>
    </ul>
    </div>

    <div class="associatedinfo">
    <p>Information for Jill</p>
    <ul>
      <li><input name="associated[12][]" /></li>
      <li><input name="associated[12][]" /></li>
    </ul>
    </div>
    <div id="newperson">
      <form action="newform.php">
        <p>Add another person:</p> 
        <input name="extra" /><input type="submit" value="Add" />
      </form>
    </div>
  </div>
</div>
</form>

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

Каков наилучший способ решить эту проблему?

4b9b3361

Ответ 1

Единственное, что вы могли бы сделать, это не устанавливать тип входного элемента "Добавить" для "отправки", установить его на "button" и добавить атрибут id для регистрации обработчика кликов:

<!-- ... -->
    <div id="newperson">
      <p>Add another person:</p> 
      <input id="extra_input" name="extra" /><input id="add_button" type="button" value="Add" />
    </div>
<!-- ... -->

Причина типа ввода "button" заключается в том, что результирующая кнопка на странице выглядит точно так же, как кнопка отправки, но при нажатии на нее ничего не делает по умолчанию, что позволяет настраивать ее эффект. Кроме того, тип ввода "button" поддерживается во всех браузерах, поддерживающих HTML 3.2 или более поздние версии включая HTML 5.

Где-то в вашем Javascript у вас, вероятно, есть функция, которую вы хотите вызвать, когда пользователь нажимает кнопку "Добавить". Предполагая, что он называется addAnotherPerson, вы просто вызываете addAnotherPerson внутри обработчика кликов:

// This is jQuery code, but all JS frameworks that I have seen have a similar feature to register a click handler on a DOM element referenced by ID.
$("#add_button").click(function (event) {
    addAnotherPerson();
    $("#extra_input").val(""); // reset the value
});

Вам также необходимо добавить обработчик keydown к "лишнему" текстовому вводу для выполнения того же действия, когда пользователь нажимает клавишу Enter:

$("#extra_input").keydown(function (event) {
    if (event.keyCode == 0xa || event.keyCode == 0xd) {
        addAnotherPerson();
        $("#extra_input").val(""); // reset the value
    }
});

Обязательно добавьте атрибут autocomplete="off" в "дополнительный" ввод текста.

Функция addAnotherPerson могла бы отправить асинхронный запрос POST, содержащий значение в "лишнем" текстовом поле, после чего обновив DOM, если это необходимо.

EDIT: Если вы также хотите поддерживать пользователей, у которых отключен Javascript, добавив атрибуты name к каждой кнопке отправки с уникальным значением атрибута name для каждого из них, на стороне сервера приложение сможет указать, на какую кнопку нажал пользователь.

Возьмем, к примеру, этот код из http://www.alanflavell.org.uk/www/trysub.html:

<table>
<tr><td align=left><label for="aquavit_button"><input id="aquavit_button" type="submit" name="aquavit" value="[O]"> Aquavit</label></td></tr>
<tr><td align=left><label for="beer_button"><input id="beer_button" type="submit" name="beer" value="[O]"> Beer</label></td></tr>
<tr><td align=left><label for="champagne_button"><input id="champagne_button" type="submit" name="champagne" value="[O]"> Champagne</label></td></tr>
<tr><td align=left><label for="water_button"><input id="water_button" type="submit" name="water" value="[O]"> Dihydrogen monoxide</label></td></tr>
</table>

Если пользователь нажимает кнопку "[O]" рядом с "Beer", браузер отправляет переменную POST "пиво", но не переменную POK "aquavit", "champagne" или "water". Попробуйте http://www.alanflavell.org.uk/www/trysub.html.

Одна сложная проблема с этим методом - это случай, когда пользователь отправляет форму, нажимая клавишу Enter в текстовом вводе. Firefox отправляет переменную POST для первой кнопки отправки в форме ( "aquavit" в этом случае), в то время как Internet Explorer не отправляет переменную POST для любой из кнопок отправки. Вы можете исправить эту разницу, добавив скрытую, безымянную кнопку отправки в начало формы:

<form action="bigform.php"><input type="submit" style="display:none;" />
<!-- ... -->

EDIT2: Если вы всегда убедитесь, что значение в "лишнем" текстовом вводе очищено Javascript до отправки большой формы, вы сможете узнать, есть ли у пользователя Javascript отключены, и они нажимают клавишу Enter в "дополнительном" текстовом вводе (указывая на то, что они хотят, чтобы действие add-a-man выполнялось), проверяя, является ли "дополнительная" POST-переменная не пустой на стороне сервера. Если он не пуст, вы можете предположить, что у пользователя отключен Javascript и что они хотят добавить человека.

Добавьте этот код:

$("#bigform").submit(function (event) {
    $("#extra_input").val(""); // reset the value in the "extra" text input
    return true;
});

Ответ 2

HTML должен быть семантическим, и его следует считать первым - то есть он должен иметь четкую структуру и значение без понимания того, что javascript лежит сверху. Подобно тому, как <ul> должен содержать только элементы <li>, a <form> должен иметь только одну цель. Использование javascript для улучшения формы путем получения динамических данных в порядке, но если используется дополнительный HTTP POST (тип, который изменяет данные на сервере), то это действительно представляет собой вторую цель, и поэтому необходимо использовать вторую форму. Вторая форма, имеющая свой собственный атрибут "действие", сигнализирует о том, что здесь происходит четкое поведение, и не только более концептуально звучит, но проще анализировать, отлаживать или расширять, когда это необходимо.

<form id="bigform" action="bigform.php">
    <!-- Tabs here -->
</form>
<form id="newperson" action="newform.php">
   <input name="extra">
   <button type="submit" value="Add">
   <!-- Note also the use of <button> instead of <input> -->
</form>

Важно то, что вы все равно можете достичь желаемого потока в основной форме. В вашей основной форме вместо использования вложенной формы используйте <fieldset>. Этот набор полей будет вести себя как прокси для формы newperson. Вход внутри здесь может иметь идентификатор, но не должен иметь имени, поскольку его значение не предназначено для отправки в основной форме. Как уже упоминалось в других ответах, кнопка должна быть заменена на тип "button", а не "отправить".

<form id="bigform" action="bigform.php">
    <!-- Tabs here -->
    <fieldset id="newpersonProxy">
        <input id="extra">
        <button type="button" value="Add">
    </fieldset>
</form>

Теперь добавьте нужное поведение ненавязчиво через Javascript, по:

  • Скрытие второй формы #newperson.
  • Ответ на "отправляет" путем привязки к событию keyup любого ввода внутри #newpersonProxy, а также к событию клика кнопки. Для события keyup используйте event.which вместо event.keyCode, поскольку jQuery нормализует это. Вы хотите event.which == 13 для ключа ввода.
  • Затем скопируйте значение из входов прокси в реальную форму, прежде чем вызывать $("#newperson").submit().

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

Кроме того, поскольку работающий HTML считался первым, простая настройка может позволить формам работать отлично без Javascript - просто скройте <fieldset> с помощью CSS и покажите его с помощью Javascript. Если Javascript выключен, вкладки разломатся, вложенный набор будет скрыт, а вторая форма будет отображаться (и полностью функционирует, только не через AJAX).

Ответ 3

Что-то вроде следующего должно это сделать.

Если JavaScript отключен, вам нужно будет определить, нажал ли пользователь "Добавить" submitButton с помощью:

$_POST["submitButton"] == "Add"


    <!-- other stuff goes here -->

    <div id="newperson">
        <p>Add another person:</p> 
        <input name="extra" id="extra" /><input name="submitButton" id="addPerson" type="submit" value="Add" />
    </div>
  </div>
</div>
</form>
<script>
    var extra = $("#extra"),
        addPerson = $("#addPerson").click(function(e){
        // val would be the new person name, e.g., "David"
        var val = extra.val();
        // you will want to give the user some AJAXy feedback here.

        $.post(this.form.action, {"extra": val}, function(response){
            // rest the extra div.
            extra.val("");

            /* 'response' could look like:                             */
            // <div class="associatedinfo">
            //      <p>Information for David</p>
            //      <ul>
            //        <li><input name="associated[13][]" /></li>
            //        <li><input name="associated[13][]" /></li>
            //      </ul>
            //   </div>
            $(response).insertBefore("#newperson");

            // or 'response' could be json data, or whatever. I have a feeling
            // you know enough about jQuery to handle the response-data.  :-)

        });
        // prevent it from bubbling up.
        e.preventDefault();
    });

    extra.keydown(function(e){
        // submit the new person name via ajax if enter is pressed.
        if(e.keyCode === 13){
            addPerson.click();
            e.preventDefault();
        }
    });
</script>

Ответ 4

Это не так много, как другие ответы, но..

Это должно быть очень просто;)

  • Полностью избавиться от ваших тегов FORM.
  • Используйте jQuery для получения значений полей ввода
  • Когда пользователь нажимает элемент submit "a", который выглядит как кнопка отправки, он просто делает запрос ajax, фиксируя значения полей ввода.

Здесь пример, который показывает немного форматирования, на которое я ссылаюсь, однако это сохраняет теги формы и является более старым примером, когда Я использовал скриптинскую библиотеку. Здесь JS, он демонстрирует немного структурирования.

Если вы +1 меня и дайте мне знать, как этот ответ, я разработаю для вас функциональный пример;)

Ура! Кирк

Ответ 5

Почему вы не вставляете объекты формы и не обрабатываете ВСЕ действия в одном PHP-коде...

# have this form appended to the DOM via ajax/js when a link is clicked
<div id="newperson">
  <p>Add another person:</p> 
  <input type="text" name="associated[new][]" />
</div>

Затем используйте php-логику на сервере, чтобы создать ассоциацию, если она "новая":

foreach($_POST['associated'] as $obj) {
  if($obj == "new")
    // create a new record
  else
    // do your other processing
}

Ответ 6

Вы можете переместить форму добавления вне родительской формы и скрыть ее с помощью CSS, затем, как сказал другой плакат, замените кнопку отправки для формы добавления кнопкой с правильным идентификатором и, наконец, зацепите обе кнопки onkeypress на входе и нажмите на кнопку, чтобы имитировать представление фактической формы добавления.

<form action="bigform.php">

    ....

    <div id="newperson">
      <p>Add another person:</p> 
      <input name="extra" /><button value="Add"/>
    </div>
  </div>
</div>
</form>
<div style='display:none;'>
    <form action="newform.php" id='add_person_form'>
      <input id='add_person_name' />
      <input type="submit" id='add_person_submit' />
    </form>
</div>

<script>
$('#newperson input').keyup(function(e) {
    if(e.keyCode == 13) submitNewPersonForm();
});
$('#newperson button').click(function(e) {
    submitNewPersonForm();
});

function submitNewPersonForm() {
    // copy the content from the placeholder form
    $('#add_person_name').val($("#newperson input").val());
    // submit this form
    $("#add_person_form").submit();
}
</script>

Это должно делать все, что вам нужно, сохраняя при этом исходную функциональность, насколько я могу судить.

Примечание. Кнопка отправки на самом деле не нужна в форме #add_person_form, я просто сохранил ее, чтобы вы могли легко увидеть, куда я переместил вашу форму.

Ответ 7

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

В противном случае другие предложения по подаче либо "внутренней" формы, либо всей формы через AJAX могут также работать.

Ответ 8

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

Ответ 9

Вы можете использовать ajax или сделать другую форму за пределами первой и поместить ее с использованием абсолютного слоя DIV.

Легко читать позицию слоя, используя javascript. Сначала вы создадите местозаполнитель с заранее определенной высотой, затем вы можете отобразить форму выше заполнителя.

<form>

...
  <div style='height: 300px;' class='placeholder'> ... </div>
</form>

<form>...<form>

Вы отобразите вторую форму, где .placeholder