Preenchimento automático de campos com base em outro campo

10

Eu tenho uma situação muito complexa em que preciso de alguns conselhos. Eu tenho um tipo de conteúdo my_content, que tem um campo de coleção de campos anexado field_mycollection, que tem um campo de referência de entidade que faz referência ao usuário field_my_userreference, um campo de telefone field_my_phone, um campo de texto field_my_texte outro campo de texto field_my_anothertext.

My Content
|_ field_mycollection
   |_ field_my_userreference
   |_ field_my_phone
   |_ field_my_text
   |_ field_my_anothertext

A entidade de usuário também tem campos field_my_phone, field_my_texte field_my_yetanothertextque este último tem um nome de máquina diferente.

O que eu quero fazer, se em um usuário my_contenteditar / adicionar formulário, field_my_userreferencefor selecionado, os outros campos deverão ser preenchidos automaticamente a partir dos dados do usuário selecionado. Os campos preenchidos automaticamente ainda devem ser editáveis.

Como eu poderia alcançar esse objetivo? Eu gostaria de fazê-lo, se possível, com alguma codificação, usando hook_form_FORM_ID_alter().

Елин Й.
fonte
Você precisa que isso aconteça ao vivo no formulário ou ao salvar?
Mołot 28/08
Viva no formulário. Eu já o implementei que, ao salvar, os dados serão retirados da entidade do usuário se deixados em branco. Mas na verdade o que eu preciso dele em forma :(
Елин Й.
OK, colocou minha resposta.
Mołot 28/08

Respostas:

11

Se você deseja que isso aconteça ao vivo e todos os campos já estejam no formulário, a maneira mais segura seria usar hook_form_FORM_ID_alter()para adicionar o seguinte a um formulário:

$form['#attached']['js'] = array(
  drupal_get_path('module', 'module_name') . '/js/copy_field_value.js',
);

Em seguida, no copy_field_value.jscomportamento de criação:

(function($) {
  Drupal.behaviors.moduleNameCopyFieldValue = {
    attach: function (context, settings) {

      // Repeat this for all fields as needed
      $('#source', context).on('blur', function () { 
        // above you can use change instead of blur if element is not changed by another js
        if (!$('#destination').val() || 0 === $('#destination').val().length) {
          $('#destination').val($(this).val());
          // wrap line above in "if no value" like I did, or other condition you like
        }
      });
      // end of "repeat this"
    }
  };
})(jQuery);

Você também pode usar hook_form_FORM_ID_alter()para adicionar #ajaxparâmetro ao campo de origem, mas faria seu formulário chamar um servidor em cada cópia de campo. Se você realmente precisa consultar o banco de dados, este é o caminho a percorrer. Seria bastante amplo descrevê-lo novamente aqui. Você precisa alterar a $form_state["input"]matriz para atualizar os valores reais vistos pelo usuário. Faça-o na função de criação de formulário, envolvendo-o issetpara evitar avisos.

Se o seu elemento de formulário estiver $form["something"]["something"]["element"], seu valor estará em $form_state["input"]["something"]["something"]["element"]- e você pode configurá-lo hook_form_altercorretamente, lembre-se de usar ambos $forme $form_statepor referência.

Nota : o .on()método foi adicionado no jQuery 1.7; portanto, você precisará do jQuery Update para usar esta resposta diretamente ou traduzir meu código para uso .change()ou .blur()método.

Mołot
fonte
Muito obrigado pelas instruções! Não estou muito bem com a API JS do Drupal. Você explicaria como obtenho os valores dos campos da entidade do usuário? Por exemplo, se um usuário é selecionado, como posso preencher os próximos campos com as informações desse usuário?
Елин Й.
11
@ ЕлинЙ. o truque aqui é não se preocupar com o fundo php. Basta identificar os parâmetros de identificação das <input>tags usando o Firebug ou uma ferramenta semelhante no seu navegador favorito. Ou use qualquer outro seletor jQuery. Isso acontecerá apenas no navegador, para que você tenha o que tem na tela. Por outro lado, se você realmente precisa consultar o banco de dados (parece que eu perdi isso), #ajaxé o caminho a percorrer. Mas seria bem amplo. Você precisa alterar a $form_state["values"]matriz para atualizar os valores reais vistos pelo usuário. Faça-o na função de criação de formulário, envolvendo-o issetpara evitar avisos.
Mołot 28/08
Mais uma vez obrigado @ Mołot, vou tentar implementá-lo amanhã, ou talvez esta noite. Parece que vou precisar de algumas horas para que realmente funcione, se não mais.
Елин Й.
@ ЕлинЙ. boa sorte, sinta-se à vontade para retornar com mais perguntas e vinculá-las aqui nos comentários, se estiverem conectadas. Resposta atualizada um pouco, aliás.
Mołot 28/08
11
Ok, eu vou experimentar um pouco e vou escrever minhas experiências.
Елин Й.
4

Você pode fazer isso usando o módulo de campo computado

O campo computado é um módulo de campo CCK muito poderoso que permite adicionar "campos computados" personalizados aos seus tipos de conteúdo. Esses campos computados são preenchidos com valores que você define via código PHP. Você pode usar qualquer coisa disponível para o Drupal, incluindo outros campos, o usuário atual, tabelas de banco de dados, etc. (Ainda está sentindo a força? :)) Você também pode optar por armazenar seus valores de campo computados no banco de dados com outros campos de conteúdo ou tê-los "calculados" rapidamente durante as visualizações de nós. (Embora você deva observar que o uso de Views requer valores armazenados no banco de dados.) Esse campo é literalmente o canivete suíço dos campos CCK. Então comece a preparar seus valores baseados em PHP!

4life
fonte
Obrigado pela resposta rápida. Parece muito promissor. No entanto, não quero instalar um módulo para isso, mas simplesmente escrever um código, pois preciso dessa funcionalidade apenas nesse formulário, e o sistema real já é muito grande e muitos módulos estão instalados para diversas funcionalidades.
Елин Й.
Em segundo lugar, é possível usar este módulo para o usuário que está criando ou editando o nó substituir os campos preenchidos automaticamente manualmente e salvar? Para que, na entidade do usuário e em my_content, diferentes valores sejam salvos.
Елин Й.
Isso vai depender da forma como ele está configurado
4Life
Obrigado @ 4life, vou tentar também se não conseguir com a codificação, usando as instruções de Mołot.
Елин Й.
2

Quero postar como consegui isso graças às ótimas ajudas do @ Mołot.

  1. Implementou o hook_form_FORM_ID_alter () .
  2. Adicionada uma div de quebra automática em torno da coleção de campos.
  3. Como a coleção my field é um campo com vários valores, iterou sobre ele e defina a #ajaxpropriedade para o campo field_my_userreference.
  4. Criou uma função de retorno de chamada que simplesmente retorna o item de coleção de campos.
  5. Verificado na implementação hook_form_FORM_ID_alter (), se $ form_state para a coleção de campos estiver definido. Se sim, obtenha os valores da entidade do usuário e preencha os campos de entrada do formulário com esses valores.

Meu código se parece com:

function MYMODULE_form_my_content_node_form_alter(&$form, &$form_state, $form_id) {
  $form['field_mycollection']['#prefix'] = '<div id="mycollection-wrapper">';
  $form['field_mycollection']['#suffix'] = '</div>';
  foreach ($form['field_mycollection']['und'] as $key => $fc_mycollection) {
    if (is_numeric($key)) {
      $form['field_mycollection']['und'][$key]['field_my_userreference']['und']['#ajax'] = array(
        'callback' => 'MYMODULE_mycollection_callback',
        'wrapper' => 'mycollection-wrapper',
      );
      if (isset($form_state['values']['field_mycollection']['und'][$key]['field_my_userreference']['und'][0]['target_id'])) {
        $user_wrapper = entity_metadata_wrapper('user', $form_state['values']['field_mycollection']['und'][$key]['field_my_userreference']['und'][0]['target_id']);
        $form_state['input']['field_mycollection']['und'][$key]['field_my_text']['und'][0]['value'] = $user_wrapper->field_my_text->value() ? $user_wrapper->field_my_text->value() : '';
        $form_state['input']['field_mycollection']['und'][$key]['field_my_anothertext']['und'][0]['value'] = $user_wrapper->field_my_text->value() ? $user_wrapper->field_my_yetanothertext->value() : '';
      }
    }
  }
}

function MYMODULE_mycollection_callback($form, &$form_state) {
  return $form['field_mycollection'];
}
Елин Й.
fonte