Làm thế nào để tạo một hình thức cần thiết với các tiểu bang?


31

Tôi có một danh sách thả xuống hiển thị các trường khác nhau dựa trên những gì được chọn và tôi biết rằng tôi có thể điều chỉnh mức độ hiển thị với các trạng thái nhưng khi tôi cố gắng sử dụng thì * span được hiển thị nhưng thực tế không bắt buộc. Ý tôi là mặc dù nó "bắt buộc" nhưng tôi có thể nhấn gửi và không nhận được thông báo lỗi từ drupal. Tôi đang làm gì đó sai hay điều này hiện đang bị hỏng trong Drupal 7.8?

        $form['host_info'] = array(
        '#type' => 'select',
        '#title' => t("Host Connection"),
        '#options' => array(
          'SSH2' => t('SSH2'),
          'Web Service' => t('Web Service'),
        ),
        '#default_value' => t(variable_get('host_info', 'SSH2')),
        '#description' => t("Specify the connection information to the host"),
        '#required' => TRUE,
    );

    $form['ssh_host'] = array(
        '#type' => 'textfield',
        '#title' => t("Host Address"),
        '#description' => t("Host address of the SSH2 server"),
        '#default_value' => t(variable_get('ssh_host')),
        '#states' => array(
            'visible' => array(
                ':input[name=host_info]' => array('value' => t('SSH2')),
            ),
            'required' => array(
                ':input[name=host_info]' => array('value' => t('SSH2')),
            ),
        ),
    );

    $form['ssh_port'] = array(
        '#type' => 'textfield',
        '#title' => t("Port"),
        '#description' => t("Port number of the SSH2 server"),
        '#default_value' => t(variable_get('ssh_port')),
        '#states' => array(
            'visible' => array(
                ':input[name=host_info]' => array('value' => t('SSH2')),
            ),
            'required' => array(
                ':input[name=host_info]' => array('value' => t('Web Service')),
            ),
        ),
    );

Bạn đang thiếu dấu ngoặc kép cho name. Nó phải như vậy :input[name="host_info"].
leymannx

Câu trả lời:


20

Bạn sẽ cần phải xác thực điều này trong một chức năng xác nhận tùy chỉnh.

Mọi thứ được định cấu hình bởi #states xảy ra 100% trong trình duyệt, mọi thứ không hiển thị cho Drupal khi biểu mẫu được gửi (ví dụ: tất cả trường biểu mẫu vô hình được gửi và xác thực theo cùng một cách nếu không có #states).


Tôi đoán đó là trường hợp. Khi tôi đang nghiên cứu cách thực hiện điều này, tôi phát hiện ra thuộc tính 'bắt buộc' với các trạng thái và nghĩ rằng nó sẽ hoạt động theo cách tôi cần mà không cần làm thêm.
Sathariel

11

Bạn có thể sử dụng yêu cầu như thế này:

'#states'=> [
  'required' => [
    ':input[name="abroad_because[somecheckbox]"]' => ['checked' => TRUE],
  ],
],

4
Có - điều này sẽ thêm chỉ báo cần thiết cho thành phần. Nhưng sẽ không có xác nhận phía máy khách hoặc máy chủ liên quan.
AyeshK


Đặt khóa yêu cầu vào mảng #states dường như hoạt động với tôi, mặc dù thực tế là tôi đã xác thực trường email. Vì vậy, tôi tự hỏi nếu bạn chỉ sử dụng drupal #element_validate mặc định trên mục biểu mẫu thì nó sẽ hoạt động?
Alex Finnarn

8

Rất giống với câu trả lời của Felix Eve, đây chỉ là đoạn trích để xác thực thành phần nội tuyến:

Bạn gọi một hàm xác thực phần tử là phần tử được yêu cầu:

$form['element'] = array(
....
  '#element_validate' => array(
     0 => 'my_module_states_require_validate',
   ),
)

Sau đó, chức năng xác thực tìm thấy trường bắt buộc và kiểm tra xem liệu nó có giá trị biểu mẫu chính xác sẽ tiết lộ trường cần được yêu cầu hay không.

function my_module_states_require_validate($element, $form_state) {
  $required_field_key = key($element['#states']['visible']);
  $required_field = explode('"', $required_field_key);
  if($form_state['values'][$required_field[1]] == $element['#states']['visible'][$required_field_key]['value']) {
    if($form_state['values'][$element['#name']] == '') {
      form_set_error($element['#name'], $element['#title'].' is required.');
    }
  }
}

1
Đây là giải pháp tốt nhất IMHO!
Alex Finnarn

3

Có một cách khác để sử dụng hàm AFTER_BUILD cho biểu mẫu và làm cho trường đó là tùy chọn. Đây là một liên kết cho drupal 6.

Thêm phần này vào mã mẫu của bạn

$form['#after_build'][] = 'custom_form_after_build';

Thực hiện sau khi xây dựng, kiểm tra điều kiện trường tùy chỉnh của bạn

function custom_form_after_build($form, &$form_state) {
  if(isset($form_state['input']['custom_field'])) {
    $form['another_custom_field']['#required'] = FALSE;
    $form['another_custom_field']['#needs_validation'] = FALSE;
  }
 return $form;
}

Trong trường hợp của tôi, #states đã thêm nhiều * vì vậy tôi phải tránh nó và sử dụng jquery để ẩn và hiển thị khoảng có chứa *

$('.another-custom-field').find('span').hide();  

$('.another-custom-field').find('span').show();

Dựa trên giá trị custom_field của tôi.


3

Dưới đây là hướng dẫn chi tiết về mẫu đơn #states của Drupal .

Đây là bit quan trọng:

/**
 * Form implementation.
 */
function module_form($form, $form_state) {
  $form['checkbox_1'] = [
    '#title' => t('Checkbox 1'),
    '#type' => 'checkbox',
  ];

  // If checkbox is checked then text input
  // is required (with a red star in title).
  $form['text_input_1'] = [
    '#title' => t('Text input 1'),
    '#type' => 'textfield',
    '#states' => [
      'required' => [
        'input[name="checkbox_1"]' => [
          'checked' => TRUE,
        ],
      ],
    ],
  ];

  $form['actions'] = [
    'submit' => [
      '#type' => 'submit',
      '#value' => t('Submit'),
    ],
  ];

  return $form;
}

/**
 * Form validate callback.
 */
function module_form_validate($form, $form_state) {
  // if checkbox is checked and text input is empty then show validation
  // fail message.
  if (!empty($form_state['values']['checkbox_1']) &&
    empty($form_state['values']['text_input_1'])
  ) {
    form_error($form['text_input_1'], t('@name field is required.', [
      '@name' => $form['text_input_1']['#title'],
    ]));
  }
}

2

Tôi vừa phải đối mặt với cùng một vấn đề cần thiết để cung cấp xác thực tùy chỉnh tuy nhiên tôi muốn điều này được kiểm soát thông qua mảng #states vì ​​vậy tôi không phải chỉ định hai quy tắc tương tự.

Nó hoạt động bằng cách trích xuất tên trường từ bộ chọn jQuery (bộ chọn phải ở định dạng :input[name="field_name"]hoặc nó sẽ không hoạt động).

Mã dưới đây chỉ được thử nghiệm trong kịch bản cụ thể mà tôi đang sử dụng, tuy nhiên tôi mặc dù nó có thể chứng minh hữu ích cho người khác.

function hook_form_validate($form, &$form_state) {

    // check for required field specified in the states array

    foreach($form as $key => $field) {

        if(is_array($field) && isset($field['#states']['required'])) {

            $required = false;
            $lang = $field['#language'];

            foreach($field['#states']['required'] as $cond_field_sel => $cond_vals) {

                // look for name= in the jquery selector - if that isn't there then give up (for now)
                preg_match('/name="(.*)"/', $cond_field_sel, $matches);

                if(isset($matches[1])) {

                    // remove language from field name
                    $cond_field_name = str_replace('[und]', '', $matches[1]);

                    // get value identifier (e.g. value, tid, target_id)
                    $value_ident = key($cond_vals);

                    // loop over the values of the conditional field
                    foreach($form_state['values'][$cond_field_name][$lang] as $cond_field_val) {

                        // check for a match
                        if($cond_vals[$value_ident] == $cond_field_val[$value_ident]) {
                            // now we know this field is required
                            $required = true;
                            break 2;
                        }

                    }

                }

            }

            if($required) {
                $field_name = $field[$lang]['#field_name'];
                $filled_in = false;
                foreach($form_state['values'][$field_name][$lang] as $item) {
                    if(array_pop($item)) {
                        $filled_in = true;
                    }
                }
                if(!$filled_in) {
                    form_set_error($field_name, t(':field is a required field', array(':field' => $field[$lang]['#title'])));
                }
            }

        }
    }

}

2

Tôi đã có thể làm theo cách này trong Drupal 8:

          '#states' => array(
            'required' => array(
              array(':input[name="host_info"]' => array('value' => 'SSH2')),
             ),
           ),

Đừng đặt t ('SSH2'). điều này sẽ đặt bản dịch của nó ở đó thay vì giá trị của tùy chọn là SSH2 chưa được dịch.

Tôi nghi ngờ rằng điều này cũng sẽ làm việc cho Drupal 7.


1
Trong drupal 7, như đã chỉ ra các câu trả lời đưa ra các giải pháp tương tự, điều này cung cấp các dấu trường bắt buộc, nhưng không thực sự thực hiện bất kỳ xác nhận nào. Liệu drupal 8 có thực sự xác nhận các trường được đánh dấu là sử dụng bắt buộc #states không?
UltraBob

0

Tôi có các trường mẫu lồng nhau và một hộp kiểm, vì vậy tôi cần làm việc một chút với câu trả lời của Dominic Woodman. Trong trường hợp bất kỳ cơ thể nào khác gặp phải vấn đề tương tự:

function my_module_states_require_validate($element, $form_state) {
  $required_field_key = key($element['#states']['visible']);
  $required_field = explode('"', $required_field_key);
  $keys = explode('[', $required_field[1]);
  $keys = str_replace(']', '', $keys);
  $tmp = $form_state['values'];
  foreach ($keys as $key => $value) {
    $tmp = $tmp[$value];
  }
  if($tmp == $element['#states']['visible'][$required_field_key]['checked']) {
    $keys2 = explode('[', $element['#name']);
    $keys2 = str_replace(']', '', $keys2);
    $tmp2 = $form_state['values'];
    foreach ($keys2 as $key => $value) {
      $tmp2 = $tmp2[$value];
    }
    if($tmp2 == '') {
      form_set_error($element['#name'], $element['#title']. t(' is required.'));
    }
  }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.