Bagaimana cara membuat formulir yang diperlukan dengan negara?

31

Saya memiliki daftar tarik-turun yang menampilkan berbagai bidang berdasarkan apa yang dipilih dan saya tahu bahwa saya dapat meningkatkan visibilitas dengan status, tetapi ketika saya mencoba menggunakan diperlukan, * span ditampilkan, tetapi sebenarnya tidak diperlukan. Maksud saya adalah bahwa meskipun "diperlukan" saya bisa menekan kirim dan tidak mendapatkan pesan kesalahan dari drupal. Apakah saya melakukan sesuatu yang salah atau apakah saat ini rusak di 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')),
            ),
        ),
    );
Sathariel
sumber
Anda melewatkan tanda kutip ganda untuk name. Pasti begitu :input[name="host_info"].
leymannx

Jawaban:

20

Anda harus memvalidasi ini sendiri dalam fungsi validasi khusus.

Segala sesuatu yang dikonfigurasikan oleh status # terjadi 100% di peramban, segala sesuatu yang dikerjakannya tidak terlihat untuk Drupal ketika formulir dikirimkan (misalnya, semua bidang formulir yang tak terlihat dikirimkan dan divalidasi dengan cara yang sama jika tidak ada # keadaan).

Berdir
sumber
Saya pikir itulah masalahnya. Ketika saya meneliti bagaimana melakukan ini, saya menemukan atribut 'wajib' dengan status dan berpikir itu akan bekerja seperti yang saya butuhkan tanpa kerja ekstra.
Sathariel
11

Anda dapat menggunakan wajib seperti ini:

'#states'=> [
  'required' => [
    ':input[name="abroad_because[somecheckbox]"]' => ['checked' => TRUE],
  ],
],
MuschPusch
sumber
4
Ya - ini akan menambahkan indikator yang diperlukan ke elemen. Tetapi tidak akan ada validasi sisi klien atau server yang terlibat.
AyeshK
Memasukkan kunci yang diperlukan ke dalam array #states sepertinya berhasil bagi saya, meskipun faktanya saya memiliki validasi bidang email. Jadi, saya ingin tahu apakah Anda hanya menggunakan drupal #element_validate default pada item formulir itu akan berfungsi?
Alex Finnarn
8

Sangat mirip dengan jawaban Felix Eve hanya ini cuplikan untuk validasi elemen inline:

Anda memanggil fungsi validasi elemen elemen yang diperlukan:

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

Kemudian fungsi validasi menemukan bidang yang diperlukan dan memeriksa untuk melihat apakah itu memiliki nilai bentuk yang benar yang akan mengungkapkan bidang yang perlu diisi.

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.');
    }
  }
}
Dominic Woodman
sumber
1
Ini adalah solusi IMHO terbaik!
Alex Finnarn
3

Ada cara lain untuk menggunakan fungsi AFTER_BUILD untuk formulir dan menjadikan bidang itu opsional. Berikut ini tautan untuk drupal 6.

Tambahkan ini ke kode formulir Anda

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

Terapkan setelah membangun, uji kondisi bidang khusus Anda

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

Dalam kasus saya, #state menambahkan beberapa * jadi saya harus menghindarinya dan menggunakan jquery untuk menyembunyikan dan menampilkan rentang yang berisi *

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

Dan

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

Berdasarkan nilai custom_field saya.

atyagi
sumber
3

Berikut panduan terperinci tentang status Drupal 7 dari status # .

Ini adalah bagian penting:

/**
 * 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'],
    ]));
  }
}
Wim Mostrey
sumber
2

Saya baru saja dihadapkan dengan masalah yang sama sehingga diperlukan untuk memberikan validasi khusus namun saya ingin ini dikendalikan melalui array #states jadi saya tidak perlu menentukan aturan yang sama dua kali.

Ini bekerja dengan mengekstraksi nama bidang dari pemilih jQuery (pemilih harus dalam format :input[name="field_name"]atau tidak akan berfungsi).

Kode di bawah ini hanya diuji dalam skenario spesifik yang saya gunakan, namun saya pikir itu mungkin bermanfaat bagi orang lain.

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'])));
                }
            }

        }
    }

}
Felix Eve
sumber
2

Saya bisa melakukannya dengan cara ini di Drupal 8:

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

Jangan letakkan t ('SSH2'). ini akan menempatkan terjemahannya di sana alih-alih nilai opsi yang merupakan SSH2 yang tidak diterjemahkan.

Saya menduga bahwa ini akan bekerja untuk Drupal 7 juga.

Akan
sumber
1
Dalam drupal 7, seperti yang ditunjukkan pada jawaban yang memberikan solusi serupa, ini memberikan tanda bidang yang diperlukan, tetapi tidak benar-benar melakukan validasi apa pun. Apakah drupal 8 benar-benar memvalidasi bidang yang ditandai sebagai kondisi # yang diperlukan?
UltraBob
0

Saya memiliki bidang formulir bersarang, dan kotak centang, jadi saya perlu bekerja sedikit pada jawaban Dominic Woodman. Jika ada orang lain yang mengalami masalah yang sama:

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.'));
    }
  }
}
Koli
sumber