Я как-то писал как добавлять элементы в форму с помощью 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']
).
- Показать второй шаг многошаговой формы в модальном окне
- Навесить на элемент managed_file свой ajax callback (Как обновить всю форму при загрузки файла в managed_file)
- Восстанавливаем позицию текстового курсора при ajax обновлении формы
- Как выполнять свой js-код до или после любых AJAX запросов (изменение работы AJAX API)
- AJAX в форме корзины Commerce 2
Комментарии
Мне нужно, чтобы форма отрабатывала по клику на одном из чекеров.
Ну есть кучка чекеров. Клик по одному - форма отработала. Без кнопки сабмита.
Верно понял, что вариант с ajax селектом - самое оно, что мне нужно. И можно ли обойтись без ajax в принципе?
без кнопки форму нельзя отправить
И ничего не наколдовать? =(
ajax
Лол. я же и уточняю. Твой пример с ajax селектом - аккурат тот случай? ))
не понимаю какой "тот случай", формы можно делать как с ajax так и без
В смысле, спрятать кнопку сабмита и отрабатывать форму по тыцанию в който произвольно выбранный чекер. Уже понял, что таки оно. Накопалась еще парочка примеров. Осталось не тупить )
Скажите пожалуйста, а если на форме много элементов select и они отрабатываются по ajax через submit-кнопку, то можно ли в submit-функции каким-то образом узнать, какой из select-элементов был задействован ?
$form_state['triggering_element'] в этом случае возвращает submit-кнопку, а не select.
Подскажите, а "с помощью свойства #ajax['trigger_as'] будет эмулировать нажатие кнопки:" для д8 тоже должно работать?
Добавить комментарий