Comment puis-je implémenter la soumission d'un formulaire AJAX?

14

Ma tâche est de soumettre le formulaire de contact via AJAX et ensuite de montrer "Merci pour la soumission!" message, chargé à l'endroit où se trouvait le formulaire. J'ai donc besoin d'ajaxifier le formulaire de contact existant.

J'ai trouvé quelques exemples comment valider des champs de formulaire en utilisant AJAX dans D8, mais je ne trouve aucun exemple comment implémenter la soumission de formulaires ajax et charger du contenu via AJAX.

Comment mettre en œuvre ma tâche? Comment dois-je modifier le formulaire de contact pour ajouter les fonctionnalités requises?

Sergey Kravchenko
la source
Pour ceux qui arrivent ici avec une question de formulaire générique: le module Webform vous permet de créer un formulaire comme vous le souhaitez et de laisser les résultats être soumis via ajax.
Florian Müller

Réponses:

26

Lorsque vous travaillez avec ajax dans des formulaires, vous devez garder à l'esprit les éléments suivants:

  • savoir si vous reconstruisez le formulaire entier ou seulement une partie de celui-ci et encapsulez le formulaire en conséquence avec l' élément div qui a l' attribut ID que vous utiliserez dans la définition #ajax sur l'élément déclencheur comme «wrapper». Utilisez les attributs #prefix et #suffix pour ceci ( $form['#prefix'] = '<div id="myform-ajax-wrapper">'; $form['#suffix'] = '</div>';). Gardez également à l'esprit que si vous avez un modèle personnalisé pour votre formulaire pour NE PAS rendre le préfixe et le suffixe dans ce cas ( {{ form|without('#prefix', '#suffix') }}) sinon ils seront rendus deux fois - par votre modèle et également par l'encapsuleur de thème de formulaire. Vous ne pouvez pas empêcher cela en définissant #theme_wrappers sur un tableau vide car le modèle de formulaire contient l'élément HTML réel du formulaire.

  • dans votre gestionnaire de soumission ajax, renvoyez le formulaire entier ou une partie de celui-ci que vous avez encapsulé et que vous souhaitez reconstruire ( return $formou return $form['myelement']). Vous pouvez également utiliser des commandes ajax au lieu de simplement renvoyer la structure du formulaire, mais ce sont des choses plus avancées.

  • stocker chaque valeur dans le stockage de l'état du formulaire jusqu'à ce que vous soumettiez le formulaire. Faites-le dans le gestionnaire de soumission ( $form_state->set('somevalue', $form_state->getValue('somevalue'))) et appelez toujours $form_state->setRebuild()si vous ne faites pas la soumission du formulaire final. Je préfère avoir des gestionnaires de soumission personnalisés, mais avoir plus de logique dans le gestionnaire de soumission principal est également tout à fait correct.

  • utilisez toujours l' #nameattribut sur le bouton qui effectue la soumission et si vous n'avez qu'un seul gestionnaire de soumission, utilisez $for_state->getTriggeringElement()['#name']pour détecter quel élément a soumis le formulaire.

  • si vous utilisez 'trigger_as' dans la définition #ajax, dans le cas où vous souhaitez soumettre le formulaire avec l'élément select par exemple, utilisez toujours la même définition #ajax comme vous le faites sur le bouton. D'après mon expérience, cela est nécessaire - bien que cela ne soit pas indiqué dans la documentation.

  • l'utilisation #limit_validation_errorspeut parfois être très délicate et comprendre pourquoi le formulaire ne fonctionne pas peut prendre un certain temps, alors utilisez-le soigneusement (c'est bon pour isoler les erreurs de formulaire uniquement sur les éléments que vous reconstruisez réellement afin que votre code n'influence pas les autres parties du formulaire).

  • utilisez toujours des boutons pour soumettre le formulaire et si vous voulez avoir quelque chose de fantaisiste, comme choisir d'être l'élément déclencheur, utilisez l'option 'trigger_as' de la configuration #ajax et cachez le vrai bouton avec la classe 'js-hide' pour une bonne interface utilisateur.

  • dans la définition de formulaire, obtenez les valeurs par défaut du stockage de l'état du formulaire si elles existent ou affectez-les dans le stockage si ce n'est pas le cas. Sinon, le formulaire ne fonctionnera pas correctement.

  • n'utilisez pas $ this ou toute autre chose à laquelle vous n'avez pas accès en externe, sinon cela cassera l'ajax. utilisez toujours des gestionnaires ajax statiques.

  • lors de la soumission finale du formulaire, selon que vous n'avez (pas) de gestionnaire de soumission de formulaire personnalisé pour ajax, désactivez la reconstruction du formulaire en appelant $form_state->setRebuild(FALSE).

  • vous pouvez utiliser les appels :: shorthand dans l'élément ajax submit ( $element['#ajax']['callback'] = '::ajaxFormRebuild';et $element['#submit'] = [['::ajaxFormSubmitHandler'];).

  • le rappel ajax consiste uniquement à renvoyer le formulaire reconstruit ou les commandes ajax. Ne retournez jamais de formulaire modifié (c.-à-d. Ne modifiez pas le tableau de formulaires dans ce rappel).


la source
Grande liste de contrôle, si vous avez des problèmes avec ajax dans drupal 8! (Je ne comprends pas le premier point, pourquoi ne PAS rendre le div de l'enveloppe ajax?)
4k4
Je ne me souviens pas exactement, mais je pense que cela pourrait avoir quelque chose à voir avec #theme, #theme_wrappers et la gestion des attributs #prefix et #suffix dans le moteur de rendu. Je pense que vous vous retrouveriez avec le wrapper à l'intérieur de l'élément <form>. Bien sûr, cela ne s'applique que si vous reconstruisez le formulaire entier, pas seulement un élément.
Merci, mais où puis-je trouver un exemple simple de soumission AJAX?
Sergey Kravchenko
@IvanJaros, merci pour la réponse. Savez-vous comment effacer les valeurs d'un formulaire après une soumission ajax?
milkovsky
1

Pour ajouter à cette liste de contrôle, si vous affichez un formulaire dans une fenêtre modale, il est possible que les messages d'erreur ne s'affichent pas. Comme l'a dit Ivan Jaros, vous devez vous assurer que le formulaire a un wrapper:

$form['#prefix'] = '<div id="my-form-wrapper-id">';
$form['#suffix'] = '</div>';

Vous devrez également ajouter ce qui suit à l'élément qui soumet le formulaire. Dans la plupart des cas, ce serait votre bouton d'envoi:

$form['submit'] = [
    '#type' => 'submit',
    '#value' => $this->t('Save Changes'),
    '#attributes' => [
        'class' => [
            'btn',
            'btn-md',
            'btn-primary',
            'use-ajax-submit'
        ]
    ],
    '#ajax' => [
        'wrapper' => 'my-form-wrapper-id',
    ]
];
IslandDev
la source
1

J'utilise le module Contact ajax . Quelques détails supplémentaires (à partir de sa page de projet):

Contact Ajax implémente la soumission ajax pour le formulaire de contact dans Drupal 8.

Comment ça fonctionne

Après avoir activé le module, chaque formulaire de contact affichera une case à cocher "Utiliser ajax". Lorsque cette case à cocher est activée, le formulaire de contact vous montrera une autre option "Type de confirmation" avec ces options:

  • Charger le formulaire: enverra le formulaire sans recharger la page.
  • Charger depuis un message personnalisé: chargez un texte personnalisé.
  • Charger depuis le nœud: charger un nœud après la soumission du formulaire.

Ce module pourrait vous aider si:

  • vous devez personnaliser le message de confirmation
  • vous devez soumettre un formulaire de contact sans recharger la page.
  • vous souhaitez charger un texte personnalisé ou un autre nœud après la soumission du formulaire.
masdzen
la source