Comment puis-je désactiver une seule case à cocher dans un élément FAPI «cases à cocher»?

31

Le titre dit tout, je veux désactiver une seule case à cocher d'un élément FAPI de type cases à cocher .

Je ne veux pas faire si avec JavaScript, ni le changer de cases à plusieurs cases à cocher des éléments comme une option l'élément est fourni par un autre module.

Pensées?

Déchiffrer
la source
Il y a une faute de frappe dans votre question: "désactiver"
FR6

Réponses:

36

Une façon propre existe dans Drupal 7! Apparemment, d' après cet article , ce n'est pas encore documenté.

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#disabled'] = TRUE; //disables all options
  $form['checkboxes_element'][abc]['#disabled'] = TRUE; //disables option, called abc
}

Un autre exemple .

Vous pouvez également définir la fonction #access sur FALSE, pour masquer complètement la case à cocher.

timofey.com
la source
3
Avec la faute de frappe corrigée, ce code fonctionne absolument pour moi en D7. Merci!
beth
1
Superbe capture! Heureux que cela ait fonctionné pour vous.
timofey.com
2
Si vous utilisez #access, si la case à cocher est définie dans les # valeurs par défaut, elle ne sera pas définie dans les valeurs d'état du formulaire lors de la soumission.
Nick
Cela fonctionne bien.
David Meister
Ne fonctionnera pas avec les cases à cocher (peut sélectionner plusieurs éléments) en utilisant de meilleurs filtres exposés (BEF) dans les vues, AFAICT.
1kenthomas
22

Malheureusement, il n'y a pas de moyen vraiment propre de le faire dans FAPI. Votre meilleur pari - si vous êtes déterminé - est de modifier une fonction #process supplémentaire sur l'élément checkboxes.

La fonction par défaut ajoutée aux éléments de type 'cases à cocher' est en fait une fonction ( expand_checkboxes () ) divise l'élément unique en plusieurs éléments de type 'case à cocher' qui sont ensuite fusionnés en un seul. Si vous deviez superposer votre deuxième fonction de processus, elle pourrait atteindre le groupe étendu d'éléments de «case à cocher» et désactiver celui en question.

Le code suivant est totalement non testé, donc mettez en garde emptor:

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#process'][] = 'mymodule_disable_element';
}

function mymodule_disable_element($element) {
  foreach (element_children($element) as $key) {
    if ($key == YOUR_CHECK_VALUE) {
      $element[$key]['#disabled'] = TRUE;
      return;
    }
  }
}
Eaton
la source
Sonne mieux que l'approche que j'ai adoptée, qui consistait à attacher une fonction de thème à l'élément et à exécuter un preg_replace()sur la sortie.
Déchiffrer
Vous pouvez ajouter une "pause"; à l'intérieur de l'instruction if ci-dessus pour un peu plus d'efficacité, sauf si vous vous attendez à voir deux fois la même clé d'élément.
Chris Cohen
Bonne prise, Chris, j'ai changé l'extrait de code. Merci!
Eaton
2
La réponse acceptée semble un peu exagérée par rapport à la réponse de @ timofey.
Citricguy
6

Voici mon code pour Drupal 7, pour changer l'élément Roles dans la page Edit User.

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#pre_render'][] = 'form_process_checkboxes'; // I had to add this one, or it will return the first role only with my callback bellow
  $form['checkboxes_element']['#pre_render'][] = 'mymodule_disable_element';
}

function mymodule_disable_element(($element) {
  foreach (element_children($element) as $key) {
    if ($key == YOUR_CHECK_VALUE) {
      $element[$key]['#attributes']['disabled'] = 'disabled';
    }
  }
  return $element;
}
aFeijo
la source
3

J'utilise des cases à cocher comme "attribuer" et "annuler l'attribution". Le client a demandé que je désactive "annuler l'attribution", mais il est toujours important de représenter "l'affectation". Gardant à l'esprit que les cases à cocher DÉSACTIVÉES sont soumises comme "fausses" et si elles ne sont pas gérées correctement, je ne les attribuerai pas. Voici comment:

// Provide LIVE checkboxes only for un-assigned Partners
$form['partner']['partners'] = array(
  '#type' => 'checkboxes',
  '#options' => array_diff($partners, $assignments),
  '#title' => t($partnername),
);
// Provide DISABLED checkboxes for assigned Partners (but with a different variable, so it doesn't get processed as un-assignment)
$form['partner']['partner_assignments'] = array(
  '#type' => 'checkboxes',
  '#options' => $assignments,
  '#default_value' => array_keys($assignments),
  '#disabled' => TRUE,
  '#title' => t($partnername),
);

Notez que «partner_assignments» est son propre tableau / variable et ne sera pas traité comme «unassign», dans mon cas d'utilisation. Merci d'avoir posté - cela m'a conduit à cette solution.

texas-bronius
la source
3

D7. Ici, nous devions nous assurer que lors de l'ajout d'un nœud, une certaine option de référence de terme de taxonomie est toujours incontrôlable et sera toujours enregistrée dans le nœud. Nous sommes donc allés dans #after_build et avons désactivé cette certaine option, mais nous devions nous assurer qu'à la fin cette certaine option serait transmise. Parce que la désactiver uniquement aurait arrêté le déplacement de cette option vers les futurs crochets.

// a constant
define('MYTERM', 113);

/**
 * Implements hook_form_alter().
 */
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
    if ($form_id == 'MYCONTENTTYPE_node_form') {
    $form['#after_build'][] = 'MYMODULE_MYCONTENTTYPE_node_form_after_build';
    }
}

/**
 * Implements custom after_build_function()
 */
function MYMODULE_MYCONTENTTYPE_node_form_after_build($form, &$form_state) {
  foreach (element_children($form['field_MYFIELD'][LANGUAGE_NONE]) as $tid) {
    if ($tid == MYTERM) {
      $element = &$form['field_MYFIELD'][LANGUAGE_NONE][$tid];
      $element['#checked'] = TRUE;
      $element['#attributes']['disabled'] = 'disabled';
    }
  }
  // here's ensured the term's travel goes on
  $form['field_MYFIELD'][LANGUAGE_NONE]['#value'] += drupal_map_assoc(array(MYTERM));
  return $form;
}

Voilà à quoi ressemble l'option désactivée:

entrez la description de l'image ici

leymannx
la source
2

Je n'ai pas pu faire fonctionner la réponse d'Eaton telle qu'elle est écrite (le rappel #process ne renvoie rien, et il est appelé avant que les cases à cocher ne soient développées) et je voulais également que la valeur soit renvoyée par la case à cocher désactivée (je voulais qu'elle soit vérifiée en permanence ). Cela a fonctionné pour moi (D6).

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#process'][] = 'mymodule_disable_element';
}

function mymodule_disable_element($element) {
  $expanded = expand_checkboxes($element);
  $checkbox =& $expanded[YOUR_CHECK_VALUE];
  $checkbox['#disabled'] = TRUE;
  $checkbox['#value_callback'] = 'mymodule_element_value_callback';
  return $expanded;
}

function mymodule_element_value_callback($element, $edit = FALSE) {
  // Return whatever value you'd like here, otherwise the element will return
  // FALSE because it's disabled.
  return 'VALUE';
}

Si quelqu'un connaît une manière plus nette, j'aimerais l'entendre!

Andy
la source
Fatal error: Call to undefined function expand_checkboxes()
leymannx
1
@koivo C'était une réponse D6, la fonction n'existe plus dans D7
Andy
1

Voici mon code pour Drupal 7, pour changer l'élément Roles dans la page Edit User.

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#pre_render'][] = 'form_process_checkboxes'; // I had to add this one, or it will return the first role only with my callback bellow
  $form['checkboxes_element']['#pre_render'][] = 'mymodule_disable_element';
}

function mymodule_disable_element(($element) {
  foreach (element_children($element) as $key) {
    if ($key == YOUR_CHECK_VALUE) {
      $element[$key]['#attributes']['disabled'] = 'disabled';
      return $element;
    }
  }
  return $element;
}
jrockowitz
la source
1

Dans Drupal 7, afin de désactiver les options dans une sélection dans une entité champable, j'ai constaté que je devais installer une #processfonction. Malheureusement, cela a désactivé la fonction de processus intégrée, form_process_checkboxesce qui doit être ajouté (ou appelé à partir de votre fonction de processus). De plus, lors de la désactivation des cases à cocher qui sont déjà cochées, j'ai découvert que la valeur intégrée callback ( form_type_checkboxes_value) ignore les valeurs par défaut lors de la récupération des résultats de l'entrée.

$field_lang_form = &$your_form[$field][LANGUAGE_NONE];
$field_lang_form['#process'][] = 'form_process_checkboxes';
$field_lang_form['#process'][] = 'YOURMODULE_YOURFUNCTION_process';
$field_lang_form['#value_callback'] = 'YOURMODULE_form_type_checkboxes_value';

Alors quelque chose comme ça:

function YOURMODULE_YOURFUNCTION_process($element) {
  // Disallow access YOUR REASON, but show as disabled if option is set.
  foreach (element_children($element) as $field) {
    if (REASON TO DISABLE HERE) {
      if (!empty($element[$field]['#default_value'])) {
        $element[$field]['#disabled'] = TRUE;
      } else {
        $element[$club]['#access'] = FALSE;
      }
    }
  }
  return $element;
}

Et enfin:

function YOURMODULE_form_type_checkboxes_value($element, $input = FALSE) {
  if ($input !== FALSE) {
    foreach ($element['#default_value'] as $value) {
      if (THIS OPTION WAS SET AND DISABLED - YOUR BUSINESS LOGIC) {
        // This option was disabled and was not returned by the browser. Set it manually.
        $input[$value] = $value;
      }
    }
  }
  return form_type_checkboxes_value($element, $input);
}

Je n'ai trouvé aucune des autres réponses sur cette page qui fonctionnait dans ce cas.

Dan Chadwick
la source
1

Voici mon exemple (en utilisant #after_build):

$form['legal']['legal_accept']['#type'] = 'checkboxes';
$form['legal']['legal_accept']['#options'] = $options;
$form['legal']['legal_accept']['#after_build'][] = '_process_checkboxes';

Plus le rappel de fonction suivant:

function _process_checkboxes($element) {
  foreach (element_children($element) as $key) {
    if ($key == 0) { // value of your checkbox, 0, 1, etc.
      $element[$key]['#attributes'] = array('disabled' => 'disabled');
      // $element[$key]['#theme'] = 'hidden'; // hide completely
    }
  }
  return $element;
}

Testé sur Drupal 6, mais il devrait également fonctionner pour Drupal 7.


Drupal 6

Vous pouvez utiliser la fonction suivante ( source ):

/*
 * Change options for individual checkbox or radio field in the form
 * You can use this function using form_alter hook.
 * i.e. _set_checkbox_option('field_tier_level', 'associate', array('#disabled' => 'disabled'), $form);
 *
 * @param $field_name (string)
 *    Name of the field in the form
 * @param $checkbox_name (string)
 *    Name of checkbox to change options (if it's null, set to all)
 * @param $options (array)
 *    Custom options to set
 * @param $form (array)
 *    Form to change
 *
 * @author kenorb at gmail.com
 */
function _set_checkbox_option($field_name, $checkbox_name = NULL, $options, &$form) {
    if (isset($form[$field_name]) && is_array($form[$field_name])) {
        foreach ($form[$field_name] as $key => $value) {
            if (isset($form[$field_name][$key]['#type'])) {
                $curr_arr = &$form[$field_name][$key]; // set array as current
                $type = $form[$field_name][$key]['#type'];
                break;
            }
        }
        if (isset($curr_arr) && is_array($curr_arr['#default_value'])) {
            switch ($type) { // changed type from plural to singular
                case 'radios':
                    $type = 'radio';
                    break;
                case 'checkboxes':
                    $type = 'checkbox';
                    break;
            }

            foreach ($curr_arr['#default_value'] as $key => $value) {
                foreach($curr_arr as $old_key => $old_value) { // copy existing options for to current option
                    $new_options[$old_key] = $old_value;
                }
                $new_options['#type'] = $type;  // set type
                $new_options['#title'] = $value;  // set correct title of option
                $curr_arr[$key] = $new_options; // set new options

                if (empty($checkbox_name) || strcasecmp($checkbox_name, $value) == 0) { // check name or set for 
                    foreach($options as $new_key => $new_value) {
                        $curr_arr[$key][$new_key] = $value;
                    }
                }
            }
            unset($curr_arr['#options']); // delete old options settings
        } else {
            return NULL;
        }
    } else {
        return NULL;
    }
}

/*
 * Disable selected field in the form(whatever if it's textfield, checkbox or radio)
 * You can use this function using form_alter hook.
 * i.e. _disable_field('title', $form);
 *
 * @param $field_name (string)
 *    Name of the field in the form
 * @param $form (array)
 *    Form to change
 *
 * @author kenorb at gmail.com
 */
function _disable_field($field_name, &$form) {
    $keyname = '#disabled';

    if (!isset($form[$field_name])) { // case: if field doesn't exists, put keyname in the main array
        $form[$keyname] = TRUE;
    } else if (!isset($form[$field_name]['#type']) && is_array($form[$field_name])) { // case: if type not exist, find type from inside of array
        foreach ($form[$field_name] as $key => $value) {
            if (isset($form[$field_name][$key]['#type'])) {
                $curr_arr = &$form[$field_name][$key]; // set array as current
                break;
            }
        }
    } else {
        $curr_arr = &$form[$field_name]; // set field array as current
    }

    // set the value
    if (isset($curr_arr['#type'])) {
        switch ($curr_arr['#type']) {
            case 'textfield':
            default:
                $curr_arr[$keyname] = TRUE;
        }
    }
}
Kenorb
la source
D7: Même chose ici, l'utilisation de #after_build fonctionne comme vous le souhaitez. Confirmation également du paramètre désactivé à l'aide de #attribute.
SGhosh
0

J'utilise ce code suivant sur drupal 6: -

$form['statuses'] = array(
    '#type' => 'checkboxes',
    '#options' => $statuses,
    '#default_value' => $status_val,
    '#after_build' => array('legal_process_checkboxes')
    );

et la fonction de rappel est ici: -

/ ** * Traiter chaque case à cocher en fonction de 'feture' est déjà utilisé par un sous-domaine ou non. * @param Array $ element tableau de cases à cocher de formulaire * /

function legal_process_checkboxes($element) {

  foreach (element_children($element) as $key) {

    $feature_id = $key;
    $res_total = '';

    $total = feature_used($feature_id) ;

    if ($total) {
      $element[$key]['#attributes'] = array('disabled' => 'disabled');
    }
  }
  return $element;
}
Sandip Ghosh
la source
Bienvenue sur drupal.stackexchange.com! Veuillez corriger la mise en forme de votre code. Les commentaires avant la fonction legal_process_checkboxes () ont été laissés en dehors du format "code". Merci.
ermannob
0

Une chose importante à prendre en compte est que les cases à cocher désactivées ne sont pas soumises, vous pouvez donc constater que vous devez également forcer #valuela case à cocher. Par exemple:

$element['child1']['#disabled'] = TRUE;
$element['child1']['#value'] = 'child1';

Dans mon cas, sans cela, le $form_state['values']ne contenait pas ma valeur de case à cocher (qui était activée par défaut, mais désactivée).

Entaille
la source
0

Accrochez le champ de texte et créez une zone de texte dynamique avec les informations de la base de données

1 ° obtenir l'assoc. tableau de la base de données par exemple

$blah = array('test1' => 'Choose for test1', 'test2' => 'Choose for test2', ...)

2 ° Instruments hook_form_alter()

/ ** * Implémente hook_form_alter (). * form id = vues-exposés-forme * /

function test_form_alter(&$form, &$form_state, $form_id)
{
  //only for this particular form
  if ($form['#id'] == "views-exposed-form-advanced-search-page-2")
    {
       $form['phases'] = array(
           '#type' => 'checkboxes',
           '#options' => $blah,
      );
    }
}

3 ° plusieurs champs seront vérifiables!

Mathieu Dierckx
la source
0

Si vous créez votre propre formulaire, au lieu d'exécuter des fonctions form_alter / # process / # pre_render distinctes, vous pouvez simplement passer des `` cases à cocher '' à la génération d'éléments de `` cases à cocher '' individuels.

$options = array(
   1 => t('Option one'),
   2 => t('Option two'),
);

// Standard 'checkboxes' method:
$form['my_element'] = array(
  '#type' => 'checkboxes',
  '#title' => t('Some checkboxes'),
  '#options' => $options,
);

// Individual 'checkbox' method:
$form['my_element'] = array(
  '#type' => 'container',
  '#attributes' => array('class' => array('form-checkboxes')),
  '#tree' => TRUE,
  'label' => array('#markup' => '<label>' . t('Some checkboxes') . '</label>',
);
foreach ($options as $key => $label) {
  $form['my_element'][$key] = array(
    '#type' => 'checkbox',
    '#title' => $label,
    '#return_value' => $key,
  );
}
// Set whatever #disabled (etc) properties you need.
$form['my_element'][1]['#disabled'] = TRUE;

'#tree' => TRUEvous donne la même structure arborescente que la version des cases à cocher lorsque le tableau $ form_state ['values'] arrive à la validation / soumettre / reconstruire. Si vous ne pouvez pas ou ne voulez pas utiliser #tree pour une raison quelconque, donnez à chaque case à cocher une '#parents' => array('my_element', $key)propriété pour définir explicitement sa position dans la structure des valeurs.

KingAndy
la source