Drupal → Зависимый checkout pane с обязательными полями на #states
Есть шаг чекаута, на котором выведено две checkout pane. Второй pane по умолчанию скрыт и появляется только если в первом отмечен соответствующий чекбокс. Ну основная загвоздка ради которой этот пост — во втором pane есть required поля:
Задача — нужно при клике на чекбоксе показывать второй pane, а если чекбокс не отмечен то при отправке формы пропускать проверку на required.
Решение:
/** * Implements hook_form_FORM_ID_alter(): commerce_checkout_form_checkout. */ function MODULENAME_form_commerce_checkout_form_checkout_alter(&$form, &$form_state) { $form['имя_второй_панели']['#states'] = array( 'visible' => array( 'селектор_до_чекбокса' => array( 'checked' => TRUE, ), ), ); $form['#after_build'][] = 'MODULENAME_form_commerce_checkout_form_checkout_after_build'; } /** * After build callback for commerce_checkout_form_checkout(). */ function MODULENAME_form_commerce_checkout_form_checkout_after_build($form, &$form_state) { if ($form_state['process_input'] && !$form_state['values']['имя_первой_панели']['имя_поля_с_чекбоксом']['und']) { MODULENAME_remove_required($form['имя_второй_панели']); } return $form; } /** * Remove requred flag. */ function MODULENAME_remove_required(&$elements) { foreach (element_children($elements) as $key) { if (is_array($elements[$key])) { MODULENAME_remove_required($elements[$key]); } } if (!empty($elements['#required'])) { $elements['#required'] = FALSE; } }
Главное не запутаться в именах панелей и полей.
Можно попробовать реализовать это с помощью #limit_validation_errors
, но говорят это не совсем безопасно. Ещё есть вариант с ajax-ом.
Комментарии
Как то сложно. Required точно также можно проверить через #states. Здесь более подробно написано про все возможные состояния #states. К примеру
states работает на клиенте, required проверяется на сервере
Да, действительно required в #states добавляет только красную звёздочку в заголовок поля, при этом форма не ребилдится и не проверяется на обязательное поле. Можно еще поиграть с #ajax для ребилда, но тоже костыль получается.
Можно ссылку на реализацию с ajax?
https://api.drupal.org/api/drupal/includes%21ajax.inc/group/ajax/7.x
Оставить комментарий