Drupal → Зависимый checkout pane с обязательными полями на #states

23.01.2015

Есть шаг чекаута, на котором выведено две 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-ом.

Написанное актуально для
Commerce 1
Похожие записи

Комментарии

Как то сложно. Required точно также можно проверить через #states. Здесь более подробно написано про все возможные состояния #states. К примеру

$form['имя_второй_панели']['имя_поля']['#states'] = array(
    'required' => array(
      'селектор_до_чекбокса' => array(
        'checked' => TRUE,
      ),
    ),
  );

states работает на клиенте, required проверяется на сервере

Да, действительно required в #states добавляет только красную звёздочку в заголовок поля, при этом форма не ребилдится и не проверяется на обязательное поле. Можно еще поиграть с #ajax для ребилда, но тоже костыль получается.

Добавить комментарий