Динамический HTML для отправки массива с использованием jQuery - PullRequest
4 голосов
/ 02 февраля 2012

Не был слишком уверен, как именно озаглавить этот вопрос, но вот проблема, которая у меня возникла:

Мне нужно иметь возможность отправить массив или связанный список данных через форму HTML. Поскольку этот массив может иметь переменную длину, у меня есть два варианта:

  1. Использовать некоторую форму разделителя (например, разделенные запятыми элементы в списке)
  2. Наличие нескольких входов (для каждого элемента массива), динамически генерируемых при необходимости добавления новых элементов

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

Поскольку я работаю над этим, я также добавляю функциональность для нескольких типов ввода, выбирает, выбирает кратные (через разделитель) и связанные входы (например, имея два текстовых ввода для «имени» и «фамилии» «который должен быть представлен как пара)

У меня есть базовый макет того, как я думаю, что он должен работать:

(function($) { // Self-calling anonymous function to avoid namespace collisions or compatibility issues

    $.fn.dynamicList = function( options ) { // jQuery plugin definition

        /* Set up default options here */
        defaults = {
            option1: "value1",
            option2: "value2"
        };
        var options = $.extend( defaults, options );

        /* Step 1. Add a jQuery-UI plus icon to the DOM */
        /* Note: I have an option to specify where this icon should go in the DOM. It defaults right after the last input */
        plus = $("<span>").addClass( 'jquery-ui-classes' );
        this.last().after( plus );

        /* Step 2. Add a table to the DOM for displaying added values */
        /* Note: I have an option to specify where this table should go in the DOM. It defaults right after the plus icon */
        plus.after( table );

        /* Step 3. Add a handler for our plus button */
        this.delegate( plus, 'click', function() {
            /* Read the inputs, add their values to the table, empty the inputs */
            /* Also, the last column of the table contains a minus button */
            /* This is where I THOUGHT my first issue was.... */
            minus = $("<span>").addClass( 'jquery-ui-classes' );
            table.append( row ).append( minus );
        });

        /* Step 4. Add a handler for our minus button */
        /* Since the minus is created within the plus handler we can't use "minus" here */
        /* Instead I use a class name to locate it */
        this.delegate( '.jquery-ui-minus-class', 'click', function() {
            /* Remove the relevant row from the table */
            $(this).parents('tr').remove();
        });

        /* Step 5. Add our submit handler */
        this.parents('form').first().submit(function() {
            /* We want all of the data in the table to be submitted with the form */
            /* Therefore we create an input per cell and name it accordingly */
            /* The name is just the name of the original input plus "[]" to make it an array */
            /* This is where I thought my second problem was */
        });

        return this; // Maintain chain-ability

    };

)(jQuery);

Этот код вызывается для входов, которые вы хотите заменить динамическим списком. Если у вас выбрано несколько входов, они станут списком связанных данных (например, имя и фамилия). Пример того, как это вызвать, может быть следующим:

<html>
    <head>
        <!-- Include jQuery and my dynamic list library here -->
        <script>
            $('#fn,#ln').dynamicList();
        </script>
    </head>
    <body>
        <form>
            <input id="fn" name="first_name" />
            <input id="ln" name="last_name" />
        </form>
    </body>
</html>

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

Я думал, что первая проблема, с которой я столкнусь, была в обработчике плюса. Поскольку я нахожусь внутри функции, вызываемой нажатием кнопки «плюс», ключевое слово «this» теперь относится к элементу DOM значка «плюс». Я не могу взять значения входов, чтобы добавить их в таблицу. Одно из предложенных мной решений состояло в том, чтобы создать глобальную переменную, которая является копией объекта, для которого функция динамического списка была вызвана так:

    .
    .
    .
        /* Step 2. Add a table to the DOM for displaying added values */
        /* Note: I have an option to specify where this table should go in the DOM. It defaults right after the plus icon */
        plus.after( table );

        var dynamicList = this;

        /* Step 3. Add a handler for our plus button */
        this.delegate( plus, 'click', function() {
            /* Read the inputs, add their values to the table, empty the inputs */
            /* Also, the last column of the table contains a minus button */
            /* This is where I THOUGHT my first issue was.... */

            for( i = 0; i < dynamicList.length; i++ ) {
                // dynamicList.get(i) will give us each input in order
            }

            minus = $("<span>").addClass( 'jquery-ui-classes' );
            table.append( row ).append( minus );
        });
    .
    .
    .

Меня беспокоит то, что если я создаю несколько динамических списков, они переопределяют друг друга. Это правда? Если да, то как мне преодолеть это?

Моя вторая проблема, с которой я столкнулся, была похожей. После отправки формы мне нужно найти таблицу, чтобы получить значения для отправки И найти входные данные, чтобы получить имена, под которыми они должны быть представлены.

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

Uncaught TypeError: Object [object Object] has no method 'replace'
jquery-1.6.2.min.js:16
f.each.f.fn.(anonymous function)     jquery-1.6.2.min.js:17
f.fn.extend.delegate     jquery-1.6.2.min.js:17
$.fn.dynamicList     jquery.dynamicList.js:76
(anonymous function)      test.php:16
f.extend._Deferred.e.resolveWith     jquery-1.6.2.min.js:16
e.extend.ready     jquery-1.6.2.min.js:16
c.addEventListener.B     jquery-1.6.2.min.js:16

Посмотрите на строку 76 моего кода динамического списка, это следующая строка:

this.delegate( plus, 'click', function() {

Могу ли я не вызвать .delegate(), так как "this" относится к нескольким объектам jQuery? Или я не могу позвонить .delegate(), потому что «это» не является родительским элементом значка «плюс»? И как только эта проблема будет решена, как мне решить две другие мои проблемы?

РЕДАКТИРОВАТЬ -

Я изменил заголовок и нашел решение моей проблемы в строке 76. Я не совсем уверен, как работает .delegate(), потому что сначала я попытался:

this.first().parent().delegate( plus, 'click', function() {

и он все еще был расстроен из-за меня. Затем я понял, что мог бы просто использовать функцию .click() вместо этого (я вроде как дурак)

plus.click( function() {

Я использовал похожую логику при создании кнопки минус в строке. Я добавил minus.click() после создания кнопки минус и перед ее вставкой в ​​DOM, избавив меня от необходимости использовать .delegate() в любом месте кода.

До сих пор не уверен, как получить значения из полей ввода в обработчике плюса, поскольку ключевое слово "this" было перезаписано в этот момент для ссылки на кнопку плюса, а не на мои поля ввода.

1 Ответ

1 голос
/ 08 октября 2012

Я изменил заголовок и нашел решение моей проблемы в строке 76. Я не уверен, как именно .delegate () работает, потому что сначала я попытался:

this.first().parent().delegate( plus, 'click', function() {

и он все еще был расстроен из-за меня.Затем я понял, что могу просто использовать вместо этого функцию .click () (я вроде как дурак)

plus.click( function() {

Я использовал аналогичную логику при создании кнопки минус в строке.Я добавил minus.click () после создания кнопки минус и перед ее вставкой в ​​DOM, что избавило меня от необходимости использования .delegate () в любом месте кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...