Remplissage automatique des champs basé sur un autre champ

10

J'ai une situation très complexe où j'ai besoin de quelques conseils. J'ai un type de contenu my_content, auquel est associé un champ de collecte de champs field_mycollection, qui a un champ de référence d'entité faisant référence à l'utilisateur field_my_userreference, un champ de téléphone field_my_phone, un champ de texte field_my_textet un autre champ de texte field_my_anothertext.

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

L'entité utilisateur possède également des champs field_my_phone, field_my_textet field_my_yetanothertextdont ce dernier a un nom de machine différent.

Ce que je veux faire, si sous forme d' my_contentédition / ajout, dans field_my_userreferenceun utilisateur est sélectionné, les autres champs doivent être remplis automatiquement à partir des données de l'utilisateur sélectionné. Les champs remplis automatiquement doivent toujours être modifiables.

Comment pourrais-je atteindre cet objectif? J'aimerais le faire, si possible, avec un peu de codage, en utilisant hook_form_FORM_ID_alter().

Елин Й.
la source
Avez-vous besoin que cela se produise en direct sur le formulaire ou lors de l'enregistrement?
Mołot
Vivez sur la forme. Je l'ai déjà implémenté lors de l'enregistrement, que les données seront prises à partir de l'entité utilisateur si elles restent vides. Mais en fait, ce dont j'ai besoin sur le formulaire :(
Елин Й.
OK, a posé ma réponse.
Mołot

Réponses:

11

Si vous souhaitez que cela se produise en direct et que tous les champs figurent déjà dans le formulaire, le moyen le plus sûr serait d'utiliser hook_form_FORM_ID_alter()pour ajouter les éléments suivants à un formulaire:

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

Puis dans le copy_field_value.jscomportement de création:

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

Vous pouvez également utiliser hook_form_FORM_ID_alter()pour ajouter un #ajaxparamètre au champ source, mais cela rendrait votre formulaire appelant un serveur sur chaque copie de champ. Si vous devez réellement interroger la base de données, c'est la voie à suivre. Il serait assez large de le décrire à nouveau ici. Vous devez modifier le $form_state["input"]tableau pour mettre à jour les valeurs réelles vues par l'utilisateur. Faites-le dans la fonction de création de formulaire, enveloppez-le avec issetpour éviter les avis.

Si votre élément de formulaire est $form["something"]["something"]["element"], sa valeur sera en $form_state["input"]["something"]["something"]["element"]- et vous pouvez le définir hook_form_altercorrectement, n'oubliez pas de prendre les deux $formet $form_statepar référence.

Remarque : la .on()méthode a été ajoutée dans jQuery 1.7, vous aurez donc besoin de la mise à jour de jQuery pour utiliser directement cette réponse, ou traduire mon code pour l'utiliser .change()ou la .blur()méthode.

Mołot
la source
Merci beaucoup pour les instructions! Je ne suis pas très bien sur l'API JS de Drupal. Pourriez-vous expliquer comment j'obtiens les valeurs de champ de l'entité utilisateur? Par exemple, si un utilisateur est sélectionné, comment puis-je remplir les champs suivants avec les informations de cet utilisateur?
Елин Й.
1
@ ЕлинЙ. l'astuce ici n'est pas de se soucier du fond php. Identifiez simplement les paramètres d' <input>identification des balises à l'aide de Firebug ou d'un outil similaire pour votre navigateur préféré. Ou utilisez tout autre sélecteur jQuery. Cela se produira uniquement dans le navigateur, vous avez donc ce que vous avez à l'écran. D'un autre côté, si vous devez réellement interroger la base de données (il me semble que cela m'a manqué), #ajaxc'est la voie à suivre. Mais ce serait assez large. Vous devez modifier le $form_state["values"]tableau pour mettre à jour les valeurs réelles vues par l'utilisateur. Faites-le dans la fonction de création de formulaire, enveloppez-le avec issetpour éviter les avis.
Mołot
Merci encore @ Mołot, je vais essayer de l'implémenter demain, ou peut-être ce soir. Il semble que j'aurai besoin de quelques heures pour que cela fonctionne vraiment, sinon plus.
Елин Й.
@ ЕлинЙ. bonne chance, n'hésitez pas à revenir avec plus de questions et à les lier ici dans les commentaires s'ils sont connectés. Réponse un peu mise à jour, btw.
Mołot
1
Ok, je vais l'expérimenter un peu et j'écrirai mes expériences.
Елин Й.
4

Vous pouvez le faire en utilisant le module de champ calculé

Le champ calculé est un module de champ CCK très puissant qui vous permet d'ajouter des «champs calculés» personnalisés à vos types de contenu. Ces champs calculés sont remplis de valeurs que vous définissez via du code PHP. Vous pouvez utiliser tout ce qui est disponible pour Drupal, y compris d'autres champs, l'utilisateur actuel, les tables de base de données, vous le nommez. (Vous sentez encore le pouvoir? :)) Vous pouvez également choisir de stocker vos valeurs de champ calculées dans la base de données avec d'autres champs de contenu, ou de les faire "calculer" à la volée pendant les vues de nœuds. (Bien que vous deviez noter que l'utilisation de Views nécessite des valeurs stockées dans la base de données.) Ce champ est littéralement le couteau suisse des champs CCK. Alors commencez à préparer vos valeurs basées sur PHP!

4life
la source
Merci pour la réponse rapide. Cela semble très prometteur. Cependant, je ne veux pas installer un module pour cela, mais simplement écrire du code, car j'ai besoin d'une telle fonctionnalité uniquement sous cette forme, et le système réel est déjà trop gros et de nombreux modules sont installés pour diverses fonctionnalités.
Елин Й.
Deuxièmement, est-il possible à l'aide de ce module, pour l'utilisateur qui crée ou modifie le noeud de remplacer manuellement les champs remplis automatiquement et d'enregistrer? De sorte que, dans l'entité utilisateur et my_content, des valeurs différentes sont enregistrées.
Елин Й.
Cela dépendra de la façon dont il est configuré
4life
Merci @ 4life, je vais essayer aussi si je ne peux pas y arriver avec le codage, en utilisant les instructions de Mołot.
Елин Й.
2

Je veux poster comment je l'ai réalisé grâce aux grandes aides de @ Mołot.

  1. Implémentation de hook_form_FORM_ID_alter () .
  2. Ajout d'un div enveloppant autour de la collection de champs.
  3. Étant donné que la collection my field est un champ à plusieurs valeurs, itéré dessus et définissez la #ajaxpropriété du champ field_my_userreference.
  4. Création d'une fonction de rappel qui renvoie simplement l'élément de collection de champs.
  5. Vérifié dans l'implémentation hook_form_FORM_ID_alter (), si $ form_state pour la collection de champs est défini. Si oui, récupérez les valeurs de l'entité utilisateur et remplissez les champs de saisie du formulaire avec ces valeurs.

Mon code ressemble à:

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'];
}
Елин Й.
la source