Jak mogę wyłączyć pojedyncze pole wyboru w elemencie FAPI „pola wyboru”?

31

Tytuł w zasadzie mówi wszystko, chcę wyłączyć pojedyncze pole wyboru typu FAPI typu pola wyboru .

Nie chcę tego robić z JavaScriptem, nie zmieniam go z pól wyboru na wiele pól wyboru elementów wyboru, ponieważ element jest dostarczany przez inny moduł.

Myśli?

Odszyfrować
źródło
W twoim pytaniu jest literówka: „wyłącz”
FR6,

Odpowiedzi:

36

Czysty sposób istnieje w Drupal 7! Najwyraźniej w tym poście nie jest jeszcze udokumentowany.

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
}

Innym przykładem .

Możesz także ustawić funkcję #access na FALSE, aby całkowicie ukryć pole wyboru.

timofey.com
źródło
3
Po poprawieniu literówki ten kod absolutnie działa dla mnie w D7. Dziękuję Ci!
beth
1
Świetne przyjęcie! Cieszę się, że to zadziałało.
timofey.com
2
Jeśli użyjesz #access, to jeśli pole wyboru jest ustawione w #default_values, nie będzie ustawione w wartości stanu formularza podczas przesyłania.
Nick
To działa ładnie.
David Meister
Nie będzie działać z polami wyboru (można wybrać więcej niż jeden element) za pomocą Lepszych widocznych filtrów (BEF) w widokach, AFAICT.
1kenthomas
22

Niestety w FAPI nie ma naprawdę czystego sposobu na zrobienie tego. Najlepiej - jeśli jesteś zdecydowany - zmienić dodatkową funkcję #process na element pól wyboru.

Domyślna funkcja dodana do elementów typu „pola wyboru” jest w rzeczywistości funkcją ( expand_checkboxes () ) dzieli pojedynczy element na wiele elementów typu „pole wyboru”, które są później scalane z powrotem w jeden. Jeśli miałbyś zastosować drugą funkcję procesu, może sięgnąć do rozszerzonej grupy elementów „pola wyboru” i wyłączyć tę, o której mowa.

Poniższy kod jest całkowicie nieprzetestowany, więc zastrzegaj 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
źródło
Brzmi lepiej niż moje podejście, które polegało na dołączeniu funkcji elementu do elementu i przejściu preg_replace()przez wynik.
Odszyfruj
Możesz dodać „przerwa”; wewnątrz powyższej instrukcji if dla nieco większej wydajności, chyba że spodziewasz się zobaczyć ten sam klucz elementu dwa razy.
Chris Cohen,
Dobry chwyt, Chris, zmieniłem fragment kodu. Dzięki!
Eaton,
2
Przyjęta odpowiedź wydaje się nieco przesadna w porównaniu z odpowiedzią @ timofey.
Citricguy,
6

Oto mój kod dla Drupala 7, aby zmienić element Role na stronie Edytuj użytkownika.

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
źródło
3

Używam pól wyboru jako „przypisuj” i „cofnij przypisanie”. Klient poprosił mnie o wyłączenie „cofnięcia przypisania”, ale nadal ważne jest przedstawienie „przypisania”. Pamiętając, że pola wyboru WYŁĄCZONE są przesyłane jako „fałszywe” i jeśli nie są odpowiednio obsługiwane, cofną przypisanie, podzielę swoje pola wyboru na „przetwarzaj je” i „ignoruję te wyłączone”. Oto jak:

// 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),
);

Zauważ, że „partner_assignments” jest własną tablicą / zmienną i nie będzie przetwarzane jako „unignign” w moim przypadku użycia. Dzięki za wysłanie - doprowadziło mnie do tego rozwiązania.

texas-bronius
źródło
3

D7 W tym miejscu musieliśmy się upewnić, że dodając węzeł, pewna opcja odniesienia terminu taksonomicznego jest zawsze nie do sprawdzenia i zawsze zostanie zapisana w węźle. Więc przeszliśmy do #after_build i wyłączyliśmy tę opcję, ale musieliśmy się upewnić, że w końcu ta opcja zostanie przekazana. Bo tylko wyłączenie go zatrzymałoby podróż tej opcji do przyszłych haków.

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

Tak wygląda wyłączona opcja:

wprowadź opis zdjęcia tutaj

leymannx
źródło
2

Nie mogłem sprawić, aby odpowiedź Eatona działała tak, jak napisano (wywołanie zwrotne #process nic nie zwraca, i jest wywoływane przed rozwinięciem pól wyboru). Chciałem też zwrócić wartość z wyłączonego pola wyboru (chciałem, aby była trwale zaznaczona ). To zadziałało dla mnie (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';
}

Jeśli ktoś zna lepszy sposób, chciałbym to usłyszeć!

Andy
źródło
Fatal error: Call to undefined function expand_checkboxes()
leymannx
1
@koivo To była odpowiedź D6, funkcja nie istnieje już w D7
Andy
1

Oto mój kod dla Drupala 7, aby zmienić element Role na stronie Edytuj użytkownika.

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
źródło
1

W Drupal 7, aby wyłączyć opcje zaznaczenia w obiekcie polowym, stwierdziłem, że musiałem zainstalować #processfunkcję. Niestety form_process_checkboxesspowodowało to wyłączenie wbudowanej funkcji procesu , dlatego należy ją ponownie dodać (lub wywołać z funkcji procesu). Dodatkowo, wyłączając pola wyboru, które są już zaznaczone, odkryłem, że wbudowana funkcja callback ( form_type_checkboxes_value) ignoruje wartości domyślne podczas pobierania wyników z danych wejściowych.

$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';

Następnie coś takiego:

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

I w końcu:

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

Nie stwierdziłem, że w tym przypadku zadziałała żadna inna odpowiedź na tej stronie.

Dan Chadwick
źródło
1

Oto mój przykład (za pomocą #after_build):

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

Plus następujące wywołanie zwrotne funkcji:

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

Testowany na Drupal 6, ale powinien również działać na Drupal 7.


Drupal 6

Możesz użyć następującej funkcji ( źródło ):

/*
 * 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
źródło
D7: To samo tutaj, użycie #after_build działa zgodnie z oczekiwaniami. Również potwierdzanie ustawienia wyłączone za pomocą #attribute.
SGhosh,
0

Korzystam z następującego kodu w drupal 6: -

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

a funkcja oddzwaniania jest tutaj: -

/ ** * Przetwarzaj każde pole wyboru na podstawie „feture” jest już używane przez subdomenę lub nie. * @param Array $ element tablicy pól formularzy * /

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
źródło
Witamy na stronie drupal.stackexchange.com! Popraw formatowanie kodu. Komentarze przed funkcją legal_process_checkboxes () zostały pozostawione poza formatem „kodu”. Dziękuję Ci.
ermannob
0

Jedną ważną rzeczą do uwzględnienia jest to, że wyłączone pola wyboru nie są przesyłane, więc może się okazać, że musisz wymusić #valuezaznaczenie pola wyboru. Na przykład:

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

W moim przypadku bez tego $form_state['values']nie zawierało mojej wartości pola wyboru (które było domyślnie włączone, ale wyłączone).

Nacięcie
źródło
0

Zaczep pole tekstowe i utwórz dynamiczne pole tekstowe z informacjami z bazy danych

1 ° zdobądź assoc. tablica z bazy danych np

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

2 ° osprzęt hook_form_alter()

/ ** * Implementuje hook_form_alter (). * identyfikator formularza = odsłonięty formularz * /

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 ° będzie możliwe do sprawdzenia wiele pól!

Mathieu Dierckx
źródło
0

Jeśli budujesz własny formularz, zamiast uruchamiać osobne funkcje form_alter / # process / # pre_render, możesz po prostu przełączyć się z „pól wyboru” na generowanie pojedynczych elementów „pola wyboru”.

$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' => TRUEdaje taką samą strukturę drzewa, jak wersja pól wyboru, gdy tablica $ form_state ['wartości'] dotrze do sprawdzania poprawności / przesłania / odbudowania. Jeśli z jakiegoś powodu nie możesz lub nie chcesz używać #tree, nadaj każdemu polu wyboru '#parents' => array('my_element', $key)właściwość, aby jawnie ustawić swoją pozycję w strukturze wartości.

KingAndy
źródło