วิธีการสร้างแบบฟอร์มที่จำเป็นต้องมีรัฐ?


31

ฉันมีรายการแบบหล่นลงที่แสดงเขตข้อมูลต่าง ๆ ตามสิ่งที่เลือกและฉันรู้ว่าฉันสามารถทำให้มองเห็นได้ด้วยสถานะของ Google แต่เมื่อฉันพยายามใช้จำเป็นต้องใช้ * span จะแสดง แต่ไม่จำเป็นจริง ๆ สิ่งที่ฉันหมายถึงคือแม้ว่ามันจะ "จำเป็น" ฉันสามารถกดส่งและไม่ได้รับข้อความแสดงข้อผิดพลาดจาก drupal ฉันกำลังทำอะไรผิดหรือตอนนี้ 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')),
            ),
        ),
    );

nameคุณไม่มีคำพูดคู่สำหรับ :input[name="host_info"]มันจะต้องเป็น
leymannx

คำตอบ:


20

คุณจะต้องตรวจสอบด้วยตัวคุณเองในฟังก์ชั่นการตรวจสอบที่กำหนดเอง

ทุกอย่างที่กำหนดโดย #states จะเกิดขึ้น 100% ในเบราว์เซอร์ทุกอย่างที่ Drupal ไม่สามารถมองเห็นได้เมื่อส่งแบบฟอร์ม (ตัวอย่างเช่นฟิลด์แบบฟอร์มที่มองไม่เห็นทั้งหมดจะถูกส่งและตรวจสอบในลักษณะเดียวกันหากไม่มี #states)


ฉันคิดว่าเป็นกรณี เมื่อฉันค้นคว้าวิธีการทำสิ่งนี้ฉันค้นพบคุณสมบัติ 'จำเป็น' กับรัฐและคิดว่ามันจะทำงานในแบบที่ฉันต้องการโดยไม่ต้องทำงานพิเศษ
Sathariel

11

คุณสามารถใช้สิ่งที่จำเป็นเช่นนี้:

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

4
ใช่ - สิ่งนี้จะเพิ่มตัวบ่งชี้ที่ต้องการในองค์ประกอบ แต่จะไม่มีการตรวจสอบฝั่งไคลเอ็นต์หรือเซิร์ฟเวอร์ที่เกี่ยวข้อง
AyeshK

อาจเป็นข้อผิดพลาดหรือไม่? องค์ประกอบที่จำเป็นต้องใช้กับรถ #states
colan

การใส่คีย์ที่ต้องการลงในอาร์เรย์ #states นั้นดูเหมือนจะใช้ได้ผลสำหรับฉันแม้ว่ามันจะเป็นความจริงที่ว่าฉันมีการตรวจสอบความถูกต้องของฟิลด์อีเมล ดังนั้นฉันสงสัยว่าคุณเพิ่งใช้ drupal #element_validate ที่เป็นค่าเริ่มต้นกับไอเท็มฟอร์มที่ใช้งานได้หรือไม่
Alex Finnarn

8

คล้ายกับคำตอบของเฟลิกซ์อีฟเท่านั้นนี่เป็นตัวอย่างสำหรับการตรวจสอบความถูกต้องขององค์ประกอบแบบอินไลน์:

คุณเรียกใช้ฟังก์ชันการตรวจสอบองค์ประกอบองค์ประกอบที่จำเป็น:

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

จากนั้นฟังก์ชันการตรวจสอบความถูกต้องจะค้นหาเขตข้อมูลที่จำเป็นและตรวจสอบเพื่อดูว่ามีค่าแบบฟอร์มที่ถูกต้องซึ่งจะเปิดเผยเขตข้อมูลที่จำเป็นต้องมีหรือไม่

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
นี่คือทางออกที่ดีที่สุด IMHO!
Alex Finnarn

3

มีอีกวิธีในการใช้ฟังก์ชัน AFTER_BUILD สำหรับฟอร์มและทำให้ฟิลด์นั้นเป็นตัวเลือก นี่คือลิงค์สำหรับ drupal 6

เพิ่มลงในรหัสแบบฟอร์มของคุณ

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

ใช้งานหลังจากบิลด์ทดสอบสภาพของฟิลด์ที่กำหนดเอง

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;
}

ในกรณีของฉัน #states กำลังเพิ่มหลาย * ดังนั้นฉันต้องหลีกเลี่ยงและใช้ jquery เพื่อซ่อนและแสดงช่วงที่มี *

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

และ

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

ขึ้นอยู่กับค่า custom_field ของฉัน


3

นี่เป็นคำแนะนำรายละเอียดเกี่ยวกับDrupal 7 #states

นี่เป็นบิตที่สำคัญ:

/**
 * 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

ฉันเพิ่งประสบกับปัญหาเดียวกันดังนั้นจำเป็นต้องมีการตรวจสอบที่กำหนดเอง แต่ฉันต้องการให้ควบคุมผ่านอาร์เรย์ #states ดังนั้นฉันจึงไม่ต้องระบุกฎเดียวกันสองครั้ง

มันทำงานได้โดยการแยกชื่อเขตข้อมูลจากตัวเลือก jQuery (ตัวเลือกจะต้องอยู่ในรูปแบบ:input[name="field_name"]หรือไม่ทำงาน)

รหัสด้านล่างนี้ได้รับการทดสอบในสถานการณ์เฉพาะที่ฉันใช้ในอย่างไรก็ตามฉันอาจพิสูจน์ว่ามีประโยชน์กับคนอื่น

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

ฉันสามารถทำได้ด้วยวิธีนี้ใน Drupal 8:

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

อย่าใส่ t ('SSH2') สิ่งนี้จะทำให้การแปลของมันมีแทนค่าของตัวเลือกซึ่งเป็น SSH2 ไม่ได้แปล

ฉันสงสัยว่าสิ่งนี้จะใช้ได้กับ Drupal 7 ด้วย


1
ใน drupal 7 ดังที่ชี้ให้เห็นคำตอบที่ให้วิธีแก้ปัญหาที่คล้ายคลึงกันนี่เป็นเครื่องหมายฟิลด์ที่จำเป็น แต่ไม่ได้ทำการตรวจสอบความถูกต้องใด ๆ drupal 8 ตรวจสอบความถูกต้องของฟิลด์ที่ทำเครื่องหมายว่าเป็นการใช้ #states ที่ต้องการหรือไม่
UltraBob

0

ฉันมีเขตข้อมูลฟอร์มที่ซ้อนกันและช่องทำเครื่องหมายดังนั้นฉันจึงจำเป็นต้องทำงานเล็กน้อยกับคำตอบของ Dominic Woodman ในกรณีที่ร่างกายอื่นประสบปัญหาเดียวกัน:

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.'));
    }
  }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.