IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

EDI, CMS, Outils, Scripts et API PHP Discussion :

Formulaires et champs texte [Drupal]


Sujet :

EDI, CMS, Outils, Scripts et API PHP

  1. #1
    Membre Expert
    Avatar de yotta
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Septembre 2006
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 088
    Par défaut Formulaires et champs texte
    Bonjour,
    Cela fait maintenant une semaine que j'essaie vainement de comprendre le fonctionnement des formulaires de Drupal. Je précise que je suis loin d'être un spécialiste d'Ajax, je ne connais que moyennement le DOM et je débute avec Drupal.
    J'évolue sous Drupal 8.6.3, et je développe avec Netbeans configuré pour l'occasion depuis chez moi, sachant que mon Drupal se trouve sur un serveur Linux Ubuntu 18.04 LTS hébergé chez OVH.
    J'essaie de créer un module de gestion de stock pour mon boulot. C'est pourquoi en ce moment je travailles sur un formulaire de saisie d'inventaire.
    Ce dernier est constitué de plusieurs champs texte, de deux listes déroulantes contenant des choix, et de deux boutons. Un pour enregistrer la saisie, l'autre pour l'annuler.
    Voilà à quoi ressemble ce formulaire :



    Vous remarquerez que j'ai surligné trois champs dans ce cliché. Les champs "Type ou modèle :", "N° de série :" et "Description :". J'ai surligné ces champs parce qu'en fait, ces trois informations sur le matériel inventorié sont déjà connues et se trouvent dans une base de données. Le but de cet inventaire est de les compléter d'une géolocalisation du matériel, d'où les autres champs qui eux sont à renseigner manuellement.
    Dans son fonctionnement, après avoir saisi la référence dans le premier champs texte, l'utilisateur va naturellement dérouler la liste de sélection d'agence, puis celle des étages. À ce moment précis, le champ texte de la référence perd le focus ce qui a pour résultat d'un point de vue Ajax de lever l'événement 'change' pour le champ texte "Référence :". Mon code exploite cet événement pour réagir à ce moment et prend alors en charge la récupération des trois informations citées ci-dessus en vue de les placer dans les champs texte concernés :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
            $form['txt_reference'] = [
              '#type' => 'textfield',
              '#title' => $this->t('Référence (-------):'),
              '#required' => true,
              '#ajax' => [
                'callback' => [$this, 'AjaxTraiteReference'],
                'event' => 'change',
                'progress' => [
                  'type' => 'throbber',
                  'message' => t('Vérification de la référence...'),
                ],
              ],
              '#prefix' => '<span id="error-message-txt_reference"></span>',
            ];
    Cette première mécanique fonctionne très bien dans le sens où lorsque je saisi la référence et que je faits perdre le focus au champ texte, la fonction AjaxCallback est bien appelée. Voilà ce qu'elle fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
        public function AjaxTraiteReference(array &$form, FormStateInterface $form_state): AjaxResponse {
            $response = new AjaxResponse();
            $nomcible = $form_state->getTriggeringElement()['#name'];
            \Drupal\Core\Database\Database::setActiveConnection('stock');
            $database = \Drupal\Core\Database\Database::getConnection('stock');
            $verif = $database->select('materielorigine', 'mat')
              ->condition('mat.reference', $form_state->getValue('txt_reference', '#value'), '=')
              ->fields('mat', ['type', 'numserie', 'description'])->execute()->fetchAssoc();
            $rep = $verif['type'];
            $num = $verif['numserie'];
            $des = $verif['description'];
            $verif = $database->select('Inventaire', 'Inventaire')
              ->condition('Inventaire.reference', $form_state->getValue('txt_reference', '#value'), '=')
              ->fields('Inventaire', ['reference'])->execute()->fetchAssoc();
            $ctrl = $verif['reference'];
            $message = (!empty($ctrl)) ? $this->t('<P><B><I> ' . $ctrl . ' a déjà été inventorié !</B></I></P>') : $this->t('<P><B><I>Matériel inconnu ?!</B></I></P>');
            $css = ['border' => '2px solid red'];
            if ((!empty($rep) || !empty($num) || !empty($des)) && empty($ctrl)) {
              $css = ['border' => '2px solid green'];
              $message = $this->t('<P><B><I>Matériel connu non inventorié.</I></B></P>');
              $elem = [
                '#type' => 'textfield',
                '#title' => '',
                '#size' => '20',
                '#value' => $rep,
                '#attributes' => [
                  'id' => ['edit-output'],
                ],
              ];
     
              $elem2 = [
                '#type' => 'textfield',
                '#title' => '',
                '#size' => '20',
                '#value' => $num,
                '#attributes' => [
                   'id' => ['edit-output2'],
                 ],
               ];
     
              $elem3 = [
                '#type' => 'textarea',
                '#title' => '',
                '#value' => $des,
                '#rows' => 3,
                '#cols' => 30,
                '#required' => FALSE,
                '#attributes' => [
                  'id' => ['edit-output3'],
                ],
              ];
              $renderer = \Drupal::service('renderer');
              $response->addCommand(new ReplaceCommand('#edit-output', $renderer->render($elem)));
              $response->addCommand(new ReplaceCommand('#edit-output2', $renderer->render($elem2)));
              $response->addCommand(new ReplaceCommand('#edit-output3', $renderer->render($elem3)));
            }
            $response->addCommand(new CssCommand("[name=$nomcible]", $css));
            $response->AddCommand(new HtmlCommand('#error-message-txt_reference', $message));
            return $response;
        }
    Voilà le code de définition de ces trois champs texte dédiés aux valeurs connues :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
            $form['label_type_modele'] = [
              '#type' => 'markup',
              '#markup' => $this->t('Type ou modèle :'),
            ];
            $form['type_modele'] = [
              '#type' => 'textfield',
              '#title' => '',
              '#size' => '20',
              '#attributes' => [
                'id' => ['edit-output'],
              ],
            ];
            $form['saut_col3'] = [
              '#type' => 'markup',
              '#markup' => $this->t('</td><td style="border:none;">'),
            ];
            $form['label_numserie'] = [
              '#type' => 'markup',
              '#markup' => $this->t('N° de série :'),
            ];
            $form['numserie'] = [
              '#type' => 'textfield',
              '#title' => '',
              '#size' => '20',
              '#required' => FALSE,
              '#attributes' => [
                'id' => ['edit-output2'],
              ],
            ];
            $form['t2_ferme'] = [
              '#type' => 'markup',
              '#markup' => $this->t('</td></tr></table>'),
            ];
            $form['label_description'] = [
              '#type' => 'markup',
              '#markup' => $this->t('Description :'),
            ];
            $form['description'] = [
              '#type' => 'textarea',
              '#title' => '',
              '#rows' => 3,
              '#required' => FALSE,
              '#attributes' => [
                'id' => ['edit-output3'],
              ],
            ];
    Ce code fonctionne 'en apparence' à merveille. J'obtiens bien ce que je veux, à savoir, l'apparition des trois valeurs connues dans leur champ respectif.
    Cependant, au submit (click sur enregistrer), les champs texte correspondants à ces trois valeurs récupérées sont vides ???

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public function submitForm(array &$form, FormStateInterface $form_state) {
      $rep = $form_state->getValue('type_modele');
      $num = $form_state->getValue('numserie');
      $des = $form_state->getValue('description');
      ...
      ...
    Mes trois variables sont vides contrairement aux champs qui ont été renseignés manuellement et que je récupère exactement de la même manière ?....
    J'en conclu que je ne fais pas les choses correctement. J'ai tenté différentes variantes (HtmlCommand, InvokeCommand, etc...), rien n'y fait. Je ne vois pas comment je peux remplir ces champs depuis mon callback ajax et faire en sorte que mon submit les récupère.
    Si quelqu'un peut m'aider, me conseiller cela m'avancerai sérieusement.
    En résumé, comment après avoir saisi ma référence je peux remplir mes champs texte de sorte que mon submit puisse les récupérer ?
    Merci à vous.
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  2. #2
    Membre Expert
    Avatar de yotta
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Septembre 2006
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 088
    Par défaut Problème réglé
    Bonjour et bonne année à tous,
    Avec ces périodes de fêtes, je conçois parfaitement qu'il n'y ait pas eu de réponse. Ce qui ne m'a pas empêché de continuer de chercher, et j'ai trouvé la solution.
    Le problème ici est lié à mon choix initiale de commande fournie à mon AjaxResponse.
    Mon tout premier essai s'est fait avec un HtmlCommand. La seule chose possible avec ce type de réponse est de placer du texte partout dans l'élément cible (titre, prefix, suffix) mais ne concerne pas le champ texte lui-même. Le mieux que j'ai pu faire avec cette commande c'est de remplacer le champ texte par du texte (comme un markup), du coup, plus aucune possibilité d'édition de la valeur.
    Mon second essai s'est fait avec la commande ReplaceCommand. Le résultat visuel est là, et cela semble fonctionner. Cependant, comme son nom l'indique, ReplaceCommand remplace le champ texte par un autre qui est nommé automatiquement si bien que l'on ne peut pas connaître son nom, ce qui rend impossible l'accès à son contenu. Mais de toute évidence, dans le formulaire subsiste le champ initial qui lui est resté vide puisque le texte s'est placé dans le champ texte de remplacement. Résultat, aucune erreur, mais comme le champ texte d'origine reste vide, récupérer son contenu est inutile, et celui qui le remplace est innaccessible, d'où l'incapacité dans le traitement submit de récupérer le contenu affiché à l'écran.
    La réponse tient dans l'usage de la commande InvokeCommand. Cette dernière est apparemment la seule qui permette d'écrire du texte dans un champ textfield sans toucher à son identité/intégrité. Ainsi, lors du traitement submit, les données placées automatiquement par le callback Ajax sont bien accessible en récupérant tout simplement la valeur contenu dans notre champ texte initial.
    Je n'ai pas eu à modifier le code de définition des éléments du formulaire dans la méthode build, ni dans submitForm puisque maintenant, lorsque dans submitForm je récupère la valeur de mon champ texte 'type_modele' par exemple, c'est bien la valeur qui a été ajoutée automatiquement. Et si l'utilisateur l'a modifiée, c'est ce qu'il a tapé que je récupère. En fait, je n'ai fait que corriger la callback Ajax en remplaçant ReplaceCommand par InvokeCommand ainsi :

    Ajax callback :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
        public function AjaxTraiteReference(array &$form, FormStateInterface $form_state): AjaxResponse {
            $response = new AjaxResponse();
            $nomcible = $form_state->getTriggeringElement()['#name'];
            \Drupal\Core\Database\Database::setActiveConnection('stock');
            $database = \Drupal\Core\Database\Database::getConnection('stock');
            $verif = $database->select('materielorigine', 'mat')
              ->condition('mat.reference', $form_state->getValue('txt_reference', '#value'), '=')
              ->fields('mat', ['type', 'numserie', 'description'])->execute()->fetchAssoc();
            $rep = $verif['type'];
            $num = $verif['numserie'];
            $des = $verif['description'];
            $verif = $database->select('Inventaire', 'Inventaire')
              ->condition('Inventaire.reference', $form_state->getValue('txt_reference', '#value'), '=')
              ->fields('Inventaire', ['reference'])->execute()->fetchAssoc();
            $ctrl = $verif['reference'];
            $message = (!empty($ctrl)) ? $this->t('<P><B><I> ' . $ctrl . ' a déjà été inventorié !</B></I></P>') : $this->t('<P><B><I>Matériel inconnu ?!</B></I></P>');
            $css = ['border' => '2px solid red'];
            if ((!empty($rep) || !empty($num) || !empty($des)) && empty($ctrl)) {
              $css = ['border' => '2px solid green'];
              $message = $this->t('<P><B><I>Matériel connu non inventorié.</I></B></P>');
              $response->addCommand(new InvokeCommand('#edit-output', 'val' , array($rep)));
              $response->addCommand(new InvokeCommand('#edit-output2', 'val' , array($num)));
              $response->addCommand(new InvokeCommand('#edit-output3', 'val' , array($des)));
            }
            $response->addCommand(new CssCommand("[name=$nomcible]", $css));
            $response->AddCommand(new HtmlCommand('#error-message-txt_reference', $message));
            return $response;
        }
    Maintenant, mon formulaire fonctionne à la perfection
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [WD-2002] Formulaire et champs texte
    Par fracine dans le forum Word
    Réponses: 3
    Dernier message: 27/11/2013, 21h50
  2. formulaire avec champ texte et listes deroulantes liées
    Par tarah01 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 08/03/2011, 18h26
  3. [HTML] formulaire gérer les espaces dans un champs texte
    Par renofx1 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 12/01/2006, 14h17
  4. Champs textes disabled et envoi formulaire
    Par nerick dans le forum Langage
    Réponses: 6
    Dernier message: 09/01/2006, 13h52
  5. formulaire mise à jour champ texte a partir autre page
    Par laulaurent dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 07/01/2006, 00h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo