Caixas de seleção selecionadas (taxonomia) preenchem uma nova lista de seleção com valores de caixas selecionadas

7

* pergunta respondida: Ajuda necessária com hook_node_submit no módulo personalizado para salvar dados *


No Drupal 7, eu tenho um tipo de conteúdo personalizado. Neste, há uma referência de termo de seleção múltipla para selecionar categorias para esse conteúdo.

Agora preciso selecionar um da categoria selecionada anteriormente e marcá-lo de alguma forma como a categoria 'principal'.

Digamos que eu tenha um campo de referência de vários termos selecionados com as seguintes opções:

Apples
Bananas
Pears
Oranges
Grapes
Pineapples

O usuário seleciona maçãs, peras e uvas. Agora eu preciso:

  1. Crie programaticamente outro campo para cada um desses selecionados - talvez com um retorno de chamada ajax - e tenha botões de opção para que eu possa selecionar apenas um dos termos selecionados e qual seja minha categoria principal.
  2. Crie um campo de rádio próximo aos itens marcados - talvez também com ajax - onde eu possa selecionar o principal dentre os selecionados.

Alguém tem alguma idéia sobre isso?

Para ser mais claro, tenho muitas dessas listas em um tipo de conteúdo. Repetir cada lista como uma única lista de valores não é uma opção.

Eu acho que minha melhor aposta é usar o hook_form_alter()com algum tipo de retorno de chamada AJAX para criar um único botão de opção ao lado da caixa de seleção que o usuário acabou de marcar ou criar programaticamente uma nova lista de campos de rádio para cada item marcado na lista especificada.

Atualização: Ok, eu decidi que a melhor maneira de fazer isso seria criar um módulo personalizado que use ajax para criar um botão de opção para cada caixa de seleção marcada, permitindo selecionar o elemento que deve ser usado como o elemento principal.

Então, eu hook_form_alter()adicionei uma #after_buildfunção, pois precisamos aguardar a renderização do formulário antes de podermos acessar os valores dos termos fiscais.

Aqui está o meu módulo até agora. Eu uso muitos comentários para que fique claro o que estou tentando fazer:

MYMODULE.module

/**
 * Implementation of HOOK_form_alter()
 * Do the ajax form alteration
 */
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {

  // 1.CONTENT FORM
  // I created a custom content type 'content' and added a term
  // reference to it 
  if($form_id == 'content_node_form') {

    // tax term ref is the main part, so let us
    // remove title and body fields
    unset($form['body']);
    unset($form['title']);

    // do our stuff after the form has been rendered ...
    $form['#after_build'][] = 'MYMODULE_after_build';

  }
}

/**
 * after_build function for content_node_form
 */
function MYMODULE_after_build(&$form, &$form_state) {

    dsm($form);  

    // In the after_build call we can now actually use the 
    // element_children function to grab the values of the fields that
    // don't start with a hash tag #
    // in this test case 1,2,3,4 and 5

    // wrap each of the elements rendered ...
    foreach(element_children($form['field_taxonomy']['und']) as $key) {

      $form['field_taxonomy']['und'][$key] += array(

        // this is added before the element and then replaced by our callback ..
        // we use the $key value in the id so that we know which div to replace 
        // depending on which checkbox is checked ...
        '#prefix' => '<div class="taxonomy_term_wrapper">
                        <div id="callback_replace_'.$key.'">Replace Me ' . $key . '</div>',

        // this is added after the element so we basically wrap around it ..
        '#suffix' => '</div>',

        // add some ajax stuff here ...
        '#ajax' => array(
          // name of the callback function to call upon change
          'callback' => 'MYMODULE_callback',
          // the id of the element that will be replaced
          'wrapper' => 'callback_replace_'.$key,
          // replace the wrapper
          'method' => 'replace',
          // what kind of effect do we want ...
          'effect' => 'fade',
          // show progress on callback
          'progress' => array('type' => 'throbber'),
        ),
      ); 



      if (!empty($form_state['values']['field_taxonomy']['und'][$key])) {
        // the form to show upon change ...
        $form['field_taxonomy']['und']['main_cat'] = array(
          // we want a radio button
          '#type' => 'radio',
          '#title' => t('Test Title'),
          '#description' => t('Test Description ...'),
          '#default_value' => empty($form_state['values']['field_taxonomy']['und'][$key]) ?
                              $form_state['values']['field_taxonomy']['und'][$key] :
                              $form_state['values']['field_taxonomy']['und'][$key],
        );
      }

    }

  return $form;
} 

function MYMODULE_callback($form, $form_state) {
 return $form['field_taxonomy']['und']['main_cat'];
}

É assim que parece atualmente antes de marcar uma caixa:

É assim que parece atualmente antes de marcar uma caixa

O HTML do formulário renderizado é o seguinte:

captura de tela

tecjam
fonte
Não é realmente uma resposta como tal, mas tente dar uma olhada no módulo Exemplos. Tem alguns exemplos de formulários ajax legais que podem ajudá-lo junto à sua maneira :) drupal.org/project/examples
Chapabu
Olá Chapabu, obrigado pela sua resposta. Eu usei os exemplos do ajax, mas meu problema está no fato de que eu preciso usar o after_build para adicionar meu código e agora estou confuso quanto ao que ele não faz nada ... Eu adicionei muito mais código acima - incluindo meu progresso até agora com o módulo. Talvez você possa ver os erros
tecjam
hmm ... a única coisa que eu posso (rapidamente) ver diferente no seu after_build é o formato. Nos documentos do Drupal, ele diz que deve ficar assim - $ form ['# after_build'] => array ('MYMODULE_after_build');
Chapabu
Eu acredito que $ form ['# after_build'] => array ('MYMODULE_after_build'); é igual a $ form ['# after_build'] [] = 'MYMODULE_after_build'; - Observe o []
tecjam 30/11
Além disso, a função after_build parece funcionar bem, pois envolve meus termos de taxonomia na minha div personalizada e adiciona minhas divs de substituição. Apenas o retorno de chamada não trabalho ..
tecjam

Respostas:

1

crie os itens como caixas de seleção. depois de selecionados, mostre uma lista suspensa com esses itens ou outro botão de opção para selecionar a categoria principal. você pode ocultar o segundo menu suspenso usando o código a seguir até que as primeiras caixas de seleção sejam marcadas.

'#states' => array(
'visible' => array(
':input[name="your checkbox"]' => array('checked' => TRUE),
 ),
)

adicione isso ao elemento que deseja ocultar. isso ficará visível apenas quando a caixa de seleção estiver marcada.

ana
fonte
0

Que tal duas listas, uma intitulada primária que faz uma seleção e a outra múltipla. Você ainda precisará endereçar a segunda lista ou seleção para eliminar duplicações.

Ashlar
fonte
Olá e obrigado pela sua resposta. Sim, claro que funcionaria. No entanto, tenho muitas listas no conteúdo para criar a página e tê-las todas duas vezes não é uma opção. Simplesmente refiz a pergunta acima em nome de um exemplo.
tecjam