Элегантный способ группировки условно включенных полей формы «более подробно» в зависимости от «родительских» полей

0

Я разрабатываю большую форму, которая имеет много групп полей. Каждая группа будет иметь поле "main" true/false dropdown/radio button, которое, будучи установленным true, включит соответствующие группы "больше деталей" в группе.

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

Поскольку существует много из этих групп, вручную привязывать обработчики событий к каждому "основному" полю, кажется, требует много времени и повторяемости. Конечно, есть лучший способ. Как я могу элегантно реализовать эту функциональность? Представьте, что атрибут data-option может быть использован для этого эффективно.

Мой псевдокод:

- On change event handler for all fields with data-group-parent
    - For all elements with data-group-child-of == this data-group-parent, set enabled value to 

Любые другие предложения?

Теги:
forms

2 ответа

1
Лучший ответ

Это действительно все сводится к тому, как вы хотите его построить, и как вы хотите управлять им...

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

<form id="MyForm">
    <section>
        <header>
            <p>I would like to experience the best yams the world has to offer!</p>
            <select data-switch="gourmet-yams-of-the-world">
                <option value="1">true</option>
                <option value="0">false</option>
            </select>
        </header>
        <div class="big-ol-list-of-yam-options"
             data-controller="gourmet-yams-of-the-world"
             hidden>
            <!-- ... -->
        </div>
    </section>
</form>

Все, что вам действительно не хватает, это один event-listener, пара строк анализа атрибутов и некоторая магия querySelector.

// listen for onchange, check if it a "switch" that changed, and find the panel the switch controls

var isSwitch = function (el) { return el.hasAttribute("data-switch"); },
    getGroupName = function (el) { return el.getAttribute("data-switch"); },
    getGroup = function (root, groupName) {
        return root.querySelector("[data-controller=\"" + groupName + "\"]");
    },
    handleSwitch = function (evt) {
        var el = evt.target,
            switchEl = isSwitch(el),
            groupName, group, action;

        if (!switchEl) { return; }
        groupName = getGroupName(el);
        group = getGroup(MyForm, groupName);
        action = !!(+el.value); // converting it to a number (1 or 0, and then to Boolean)
        toggleGroup(group, action);
    };


MyForm.addEventListener("change", handleSwitch);

Имейте в виду, что это не гарантирует работу со всеми браузерами. Как это ни addEventListener, это браузеры, которые не поддерживают addEventListener которые также не могут addEventListener событием "change".

Есть и другие способы сделать это.

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

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

  • 0
    Отличный ответ и спасибо за подробный код. Интересно, было бы более эффективно делать это таким образом, используя опции данных или вместо этого используя классы, и связывать изменения непосредственно с коммутатором.
  • 0
    Все зависит от того, что вы собираетесь делать. Если вы ожидаете, что все они будут оформлены одинаково, классы тоже подойдут. С точки зрения производительности, если вы говорите о старом IE (который не позволяет кипящий на «изменение» событий или addEventListener или querySelector в любом случае), то он делает немного разницы, но вы можете использовать data-* атрибуты вплоть до IE6. Что касается эффективности, это действительно зависит. Этот способ использует гораздо меньше памяти, как, например, для дополнительного процессора, но только в том случае, если вы ожидаете, что пользователи пройдут через сотни изменений в считанные секунды ...
1

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

Some info
<span class="more-details"></span>
<div class="more-info">
    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info
</div>
Some info
<span class="more-details">Click for more...</span>
<div class="more-info">
    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info
</div>Some info
<span class="more-details">Click for more...</span>
<div class="more-info">
    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info
</div>Some info
<span class="more-details">Click for more...</span>
<div class="more-info">
    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info    Some more info
</div>

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

$('.more-details').text('Click for more...');
$('.more-info').hide();

Как только это будет сделано, вы можете прикрепить событие клика ко всем элементам, которые можно щелкнуть, с помощью одной функции:

$('.more-details').click(function(){

    var $span = $(this);

    if ($span.text() == 'Click for more...') {
        $span.next().show();
        $span.text('Click for less...')
    } else {
        $span.next().hide();
        $span.text('Click for more...')
    }

})

Возьмите его за спину: http://jsfiddle.net/Ckr85/

Вам не нужно использовать атрибуты данных - вы можете комбинировать группы/элементы по общему классу. И снова, используя единственную ссылку на "Показать больше/меньше", более удобно, чем радио/выпадающие меню.

  • 0
    Отличный ответ - очень просто. Интересно, что более подходит для использования классов или пользовательских атрибутов данных? Может быть, сочетание обоих?
  • 0
    Обычные атрибуты данных используются только для этого - для хранения данных. Вы можете использовать их как селекторы, но классы являются более распространенным подходом.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню