Como posso desativar uma única caixa de seleção em um elemento FAPI de 'caixas de seleção'?

31

Título basicamente diz tudo, quero desabilitar uma única caixa de seleção de um tipo de caixa de seleção elemento FAPI.

Não quero fazer isso com JavaScript, nem a alteração de caixas de seleção para vários elementos de caixa de seleção é uma opção, pois o elemento é fornecido por outro módulo.

Pensamentos?

Decifrar
fonte
Há um erro de digitação na sua pergunta: "desativar"
FR6

Respostas:

36

Existe uma maneira limpa no Drupal 7! Aparentemente, por este post , ele ainda não está documentado.

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
}

Outro exemplo .

Você também pode definir a função #access como FALSE, para ocultar completamente a caixa de seleção.

timofey.com
fonte
3
Com o erro de digitação corrigido, esse código funciona absolutamente para mim no D7. Obrigado!
beth 14/05
1
Great catch! Que bom que funcionou para você.
Timofey.com # 14/13
2
Se você usar #access, se a caixa de seleção estiver definida em #default_values, ela não será definida nos valores do estado do formulário no envio.
11743 Nick
Isso funciona bem.
David Meister
Não funcionará com caixas de seleção (pode selecionar mais de um elemento) usando os Filtros melhor expostos (BEF) nas visualizações AFAICT.
1kenthomas
22

Infelizmente, não há uma maneira realmente limpa de fazer isso na FAPI. Sua melhor aposta - se você estiver determinado - é alterar uma função #process adicional no elemento de caixas de seleção.

A função padrão adicionada aos elementos do tipo 'caixas de seleção' é na verdade uma função ( expand_checkboxes () ) divide o elemento único em vários elementos do tipo 'caixa de seleção' que são posteriormente mesclados novamente em um. Se você pegar carona com sua segunda função de processo, ela poderá acessar o grupo expandido de elementos de 'caixa de seleção' e desativar a que está em questão.

O código a seguir é totalmente não testado, portanto, ressalte o 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
fonte
Soa melhor do que a abordagem adotada, que era anexar uma função de tema ao elemento e executar uma preg_replace()sobre a saída.
Decipher
Você pode adicionar uma "pausa"; dentro da instrução if acima para obter um pouco mais de eficiência, a menos que você espere ver a mesma chave do elemento duas vezes.
Chris Cohen
Boa captura, Chris, mudei o trecho de código. Obrigado!
Eaton
2
A resposta aceita parece um pouco exagerada quando comparada à resposta de @ timofey.
Citricguy
6

Aqui está o meu código para o Drupal 7, para alterar o elemento Roles na página 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
fonte
3

Estou usando caixas de seleção como "atribuir" e "não atribuir". O cliente solicitou que eu desabilitasse "não atribuir", mas ainda é importante representar "atribuição". Tendo em mente que as caixas de seleção DESABILITADAS são enviadas como "falsas" e, se não forem tratadas adequadamente, serão desassociadas. Aqui está como:

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

Observe que 'partner_assignments' é sua própria matriz / variável e não será processado como "não atribuído" no meu caso de uso. Obrigado por postar - ele me levou a esta solução.

texas-bronius
fonte
3

D7 Aqui, tivemos que garantir que, ao adicionar um nó, uma certa opção de referência de termo de taxonomia seja sempre desmarcável e sempre será salva no nó. Então, entramos no #after_build e desativamos essa opção, mas tivemos que garantir que, no final, essa opção fosse transmitida. Porque apenas desativá-lo teria parado a viagem dessa opção para futuros ganchos.

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

É assim que a opção desabilitada se parece:

insira a descrição da imagem aqui

leymannx
fonte
2

Não consegui que a resposta da Eaton funcionasse como escrita (o retorno de chamada #process não retorna nada e é chamado antes que as caixas de seleção sejam expandidas) e também queria que o valor fosse retornado da caixa de seleção desativada (eu queria que ele fosse marcado permanentemente ) Isso funcionou para mim (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';
}

Se alguém souber de uma maneira melhor, eu adoraria ouvir!

Andy
fonte
Fatal error: Call to undefined function expand_checkboxes()
Leymannx
1
@koivo Esta foi uma resposta D6, a função não existir em D7
Andy
1

Aqui está o meu código para o Drupal 7, para alterar o elemento Roles na página 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
fonte
1

No Drupal 7, para desativar as opções em um select em uma entidade de campo, descobri que precisava instalar uma #processfunção. Infelizmente, isso desativou a função de processo interna, de form_process_checkboxesmodo que precisa ser adicionada novamente (ou chamada a partir da função de processo). Além disso, ao desativar as caixas de seleção já marcadas, descobri que o valor interno callback ( form_type_checkboxes_value) ignora os padrões ao recuperar resultados da entrada.

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

Então algo como isto:

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

E finalmente:

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

Não achei que nenhuma das outras respostas nesta página funcionasse nesse caso.

Dan Chadwick
fonte
1

Aqui está o meu exemplo (usando #after_build):

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

Mais a seguinte função de retorno de chamada:

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

Testado no Drupal 6, mas também deve funcionar no Drupal 7.


Drupal 6

Você pode usar a seguinte função ( fonte ):

/*
 * 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
fonte
D7: O mesmo aqui, usar #after_build está funcionando como desejado. Também confirmando a configuração desativada usando #attribute.
precisa saber é o seguinte
0

Estou usando este código a seguir no drupal 6: -

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

e a função de retorno de chamada está aqui: -

/ ** * Processar cada caixa de seleção com base em 'feture' já é usado por um subdomínio ou não. * @param Matriz $ elemento matriz de caixas de seleção de formulário * /

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
fonte
Bem-vindo ao drupal.stackexchange.com! Corrija a formatação do seu código. Os comentários antes da função legal_process_checkboxes () foram deixados de fora do formato "código". Obrigado.
ermannob
0

Uma coisa importante a ser levada em consideração é que as caixas de seleção desabilitadas não são enviadas, portanto, você pode achar que precisa forçar #valuea caixa de seleção também. Por exemplo:

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

No meu caso, sem isso, o $form_state['values']não continha o valor da minha caixa de seleção (que estava ativada por padrão, mas desativada).

usuario
fonte
0

Conecte o campo de texto e crie uma caixa de texto dinâmica com informações do banco de dados

1 ° obter o associado. matriz do banco de dados, por exemplo

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

2 ° Implementos hook_form_alter()

/ ** * Implementa hook_form_alter (). * ID do formulário = formulário de exibição exposta * /

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 ° campos múltiplos serão verificáveis!

Mathieu Dierckx
fonte
0

Se você estiver criando seu próprio formulário, em vez de executar as funções form_alter / # process / # pre_render separadas, basta mudar de 'caixas de seleção' para gerar elementos individuais de 'caixa de seleção'.

$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' => TRUEfornece a mesma estrutura em árvore da versão das caixas de seleção quando a matriz $ form_state ['values'] chega na validação / envio / reconstrução. Se você não puder ou não quiser usar #tree por algum motivo, atribua a cada caixa de seleção uma '#parents' => array('my_element', $key)propriedade para definir explicitamente sua posição na estrutura de valores.

KingAndy
fonte