Drupal → Правильные ajax селекты, чекбоксы и радиокнопки
Я как-то писал как добавлять элементы в форму с помощью AJAX. Форма работала, но у неё был один недостаток — элементы добавлялись только при включённом javascript.
Сложность реализации ajax селектов/радиокнопок/чекбоксов в том, что без javascript нет возможности засабмитить форму и следовательно изменить её элементы.
Решение достаточно простое — добавить кнопку, видимую только пользователям с отключённым js. Кнопка будет сабмитить форму и добавлять элементы, а select, с помощью свойства #ajax['trigger_as']
будет эмулировать нажатие кнопки:
1. Создаём форму работающую без javascript
/** * Form builder. */ function helper_form_test($form, &$form_state) { $form['fields_count_wrapper'] = array( '#type' => 'container', ); // Селект с числом полей $form['fields_count_wrapper']['fields_count'] = array( '#type' => 'select', '#title' => 'Fields count', '#options' => drupal_map_assoc(array(1, 2, 3)), ); // Кнопка для изменения числа полей в форме $form['fields_count_wrapper']['fields_count_change'] = array( '#type' => 'submit', '#value' => 'Change count', // При отправки формы с помощью этой кнопки, валидацию будет проходить только поле fields_count '#limit_validation_errors' => array( array('fields_count'), ), '#submit' => array('helper_form_test_fields_count_change'), ); // Число полей зависит от выбранного значения в fields_count $count = isset($form_state['values']['fields_count']) ? $form_state['values']['fields_count'] : 1; for ($i = 0; $i < $count; $i++) { $form['fields']['field' . $i] = array( '#type' => 'textfield', '#title' => 'Field ' . ($i + 1), '#required' => TRUE, ); } $form['submit'] = array( '#type' => 'submit', '#value' => 'Submit', ); return $form; } /** * Change count callback. */ function helper_form_test_fields_count_change($form, &$form_state) { $form_state['rebuild'] = TRUE; } /** * Submit callback. */ function helper_form_test_submit($form, &$form_state) { // ... }
2. Добавляем ajax функционал кнопке fields_count_change
/** * Form builder. */ function helper_form_test($form, &$form_state) { // ... $form['fields_count_wrapper']['fields_count_change'] = array( // ... // AJAX функционал '#ajax' => array( 'callback' => 'helper_form_test_fields_count_change_ajax', 'wrapper' => 'fields', ), ); $form['fields'] = array( '#prefix' => '<div id="fields">', '#suffix' => '</div>', ); // ... } /** * Ajax callback. */ function helper_form_test_fields_count_change_ajax($form, &$form_state) { return $form['fields']; }
3. Добавляем ajax функционал селекту fields_count и скрываем кнопку fields_count_change
/** * Form builder. */ function helper_form_test($form, &$form_state) { // ... $form['fields_count_wrapper']['fields_count'] = array( // ... // AJAX функционал '#ajax' => array( 'callback' => '', 'wrapper' => 'fields', 'trigger_as' => array('name' => 'fields_count_change'), ), ); $form['fields_count_wrapper']['fields_count_change'] = array( // ... // Скрываем кнопку '#attributes' => array( 'class' => array('js-hide'), ), ); // ... }
В этом пункте есть небольшой подводный камень — #ajax у селекта не будет работать без свойства callback
(его нужно оставить пустым) и без wrapper
(его нужно продублировать из $form['fields_count_wrapper']['fields_count_change']['#ajax']['wrapper']
).
Комментарии
Мне нужно, чтобы форма отрабатывала по клику на одном из чекеров.
Ну есть кучка чекеров. Клик по одному - форма отработала. Без кнопки сабмита.
Верно понял, что вариант с ajax селектом - самое оно, что мне нужно. И можно ли обойтись без ajax в принципе?
без кнопки форму нельзя отправить
И ничего не наколдовать? =(
ajax
Лол. я же и уточняю. Твой пример с ajax селектом - аккурат тот случай? ))
не понимаю какой "тот случай", формы можно делать как с ajax так и без
В смысле, спрятать кнопку сабмита и отрабатывать форму по тыцанию в който произвольно выбранный чекер. Уже понял, что таки оно. Накопалась еще парочка примеров. Осталось не тупить )
Скажите пожалуйста, а если на форме много элементов select и они отрабатываются по ajax через submit-кнопку, то можно ли в submit-функции каким-то образом узнать, какой из select-элементов был задействован ?
$form_state['triggering_element'] в этом случае возвращает submit-кнопку, а не select.
Подскажите, а "с помощью свойства #ajax['trigger_as'] будет эмулировать нажатие кнопки:" для д8 тоже должно работать?
Оставить комментарий