J'ai une liste déroulante qui affiche divers champs en fonction de ce qui est choisi et je sais que je peux parcourir la visibilité avec des états, mais lorsque j'essaie d'utiliser requis, la * span est affichée mais elle n'est pas réellement requise. Ce que je veux dire, c'est que même si c'est "obligatoire", je peux appuyer sur soumettre et ne pas recevoir de message d'erreur de drupal. Suis-je en train de faire quelque chose de mal ou est-ce actuellement cassé dans 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')),
),
),
);
Vous devrez le valider vous-même dans une fonction de validation personnalisée.
Tout ce qui est configuré par #states se produit à 100% dans le navigateur, tout ce qu'il fait n'est pas visible pour Drupal lorsque le formulaire est soumis (par exemple, tous les champs de formulaire invisibles sont soumis et validés de la même manière). façon s'il n'y avait pas de # états).
Vous pouvez utiliser requis comme ceci:
'#states'=> [
'required' => [
':input[name="abroad_because[somecheckbox]"]' => ['checked' => TRUE],
],
],
Très similaire à la réponse de Felix Eve, il s'agit uniquement d'un extrait de validation d'élément en ligne:
Vous appelez une fonction de validation d'élément l'élément requis:
$form['element'] = array(
....
'#element_validate' => array(
0 => 'my_module_states_require_validate',
),
)
Ensuite, la fonction de validation trouve le champ requis et vérifie s'il a la valeur de formulaire correcte qui révélerait le champ qui doit être requis.
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.');
}
}
}
Il existe une autre façon d'utiliser la fonction AFTER_BUILD pour le formulaire et de rendre ce champ facultatif. Voici un lien pour drupal 6.
Ajoutez ceci à votre code de formulaire
$form['#after_build'][] = 'custom_form_after_build';
Implémentez après la construction, testez votre condition de champ personnalisé
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;
}
Dans mon cas, #states ajoutait plusieurs * donc je dois l'éviter et j'ai utilisé jquery pour masquer et afficher la plage qui contient *
$('.another-custom-field').find('span').hide();
Et
$('.another-custom-field').find('span').show();
Basé sur ma valeur custom_field.
Voici un guide détaillé sur Drupal 7 form #states .
C'est le bit important:
/**
* 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'],
]));
}
}
J'ai pu le faire de cette façon en Drupal 8:
'#states' => array(
'required' => array(
array(':input[name="Host_info"]' => array('value' => 'SSH2')),
),
),
Ne mettez pas t ('SSH2'). cela mettra la traduction de celui-ci à la place de la valeur de l'option qui est un SSH2 non traduit.
Je soupçonne que cela fonctionnerait pour Drupal 7 aussi.
Je viens d'être confronté au même problème, donc j'avais besoin de fournir une validation personnalisée, mais je voulais que cela soit contrôlé via le tableau #states, donc je n'ai pas eu à spécifier deux fois les mêmes règles.
Il fonctionne en extrayant le nom du champ du sélecteur jQuery (le sélecteur doit être au format :input[name="field_name"]
ou ça ne marchera pas).
Le code ci-dessous n'est testé que dans le scénario spécifique dans lequel je l'utilisais, mais je pense qu'il peut s'avérer utile à quelqu'un d'autre.
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'])));
}
}
}
}
}
J'ai des champs de formulaire imbriqués et une case à cocher, donc je devais travailler un peu sur la réponse de Dominic Woodman. Au cas où un autre organisme rencontrerait le même problème:
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.'));
}
}
}