xandeadx.ru Блог музицирующего веб-девелопера

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-ом.

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

Комментарии RSS

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

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

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

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

Можно ссылку на реализацию с ajax?

Оставить комментарий

Содержимое этого поля является приватным и не будет отображаться публично. Если у вас есть аккаунт в Gravatar, привязанный к этому e-mail адресу, то он будет использован для отображения аватара.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступные HTML теги: <a> <i> <b> <strong> <code> <ul> <ol> <li> <blockquote> <em> <s>
  • Строки и параграфы переносятся автоматически.
  • Подсветка кода осуществляется с помощью тегов: <code>, <css>, <html>, <ini>, <javascript>, <sql>, <php>. Поддерживаемые стили выделения кода: <foo>, [foo].

Подробнее о форматировании