Formulaires CVT en plusieurs pages

Il est possible de créer un formulaire composé de plusieurs pages de saisies avec validation de la saisie au fur de chaque page, et un seul traitement final.

Les formulaires multi-étapes (ou multi-pages) sont une variation des formulaires CVT qui permet d’enchainer plusieurs pages de saisies, avec une validation (vérification) intermédiaire de chacune de ces pages et un traitement final qui permet de prendre en compte toutes les valeurs saisies en une seule fois.

  • Apparu en : SPIP 3.0

Il est nécessaire d’être déjà familier avec les formulaires CVT pour créer un formulaire CVT en plusieurs pages.

Nous allons voir comment construire facilement un formulaire d’inscription en 3 pages distinctes, SPIP prenant en charge la partie compliquée qui consiste à mémoriser les données déja saisies pour le traitement final, et à permettre la navigation entre les pages.

Les squelettes de chaque page

Chaque page du formulaire se présente comme un formulaire complet (avec un bouton de validation qui sert à passer à l’étape suivante).

Chacune des étape est numérotée, à partir de 1, et décrite par un fichier squelette indépendant qui implémente un formulaire autonome pour les saisies de cette page.

Pour l’étape 1, le squelette est formulaires/inscription.html.
Pour l’étape 2, le squelette est formulaires/inscription_2.html.
Pour l’étape 3, le squelette est formulaires/inscription_3.html.

Voici par exemple à quoi ressemble la première page de notre formulaire :

<div class="formulaire_spip">
	[<p class="reponse_formulaire reponse_formulaire_ok">(#ENV*{message_ok})</p>]
	[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>]
	[(#ENV{editable})
	<form method='post' action='#ENV{action}'><div>
		[(#REM) les hidden qui declencheront le service du formulaire parametre : url d'action ]
		#ACTION_FORMULAIRE{#ENV{action},#FORM}

                <!-- Ici les saisies de l'étape 1, directement en HTML. 
                       Elles pourraient aussi être générées par le plugin SAISIES  -->
                 <label>Votre email</label>
                 <input type='text' name='email' value='#ENV{email}' />               
                 <input type="submit" class="submit" value="<:pass_ok:>" />
         </div></form>
	]
</div>

À l’intérieur de chaque squelette, #ENV{_etape} renvoie le n° de l’étape, et #ENV{_etapes} renvoie le nombre total d’étapes de saisie. Cela permet par exemple d’afficher un état de l’avancement de la saisie par rapport au nombre total de pages de saisies :

<div class="formulaire_spip formulaire_inscription formulaire_#FORM  formulaire_#FORM_#ENV{_etape}">
	<h3>Inscription  #ENV{_etape} / #ENV{_etapes} : indiquez votre email</h3>
... 

A chaque page, #ENV contient toutes les valeurs déjà saisies lors des étapes précédentes. Ainsi, si vous voulez proposer une valeur par défaut qui dépend d’une saisie précédente, il suffit d’utiliser celle-ci pour pré-remplir votre saisie.

Sur chaque page, il est aussi possible de proposer un bouton qui renvoie vers une autre étape (par exemple pour faire un bouton de retour à l’étape précédente). Il suffit pour cela de donner au bouton l’attribut name avec la valeur _retour_etape_n, n désignant le numéro de l’étape visée :

<p class="boutons">
                <input type="submit" class="submit" name="_retour_etape_2" value="<:retour:>" />
        </p>

Il est possible que cette étape soit une étape en avant, mais attention : dans tous les cas l’utilisateur ne pourra passer à une étape n que si la saisie des étapes précédentes est correcte et sans erreur ! Dans le cas contraire, c’est la première page avec des erreurs qui lui sera présentée.

Rq : _retour_etape_n permettait la compatibilité avec Internet Explorer. Cet usage est deprécié : il faut désormais utiliser un input de name aller_a_etape, dont la valeur contient directement l’étape visée.

À partir de SPIP 4.0 : Pour aller directement à la validation finale, il suffit d’indiquer un n° d’étape supérieur au nombre d’étape total.

Charger et déclarer les étapes de saisie

La déclaration des étapes ou pages de saisies se fait dans la fonction charger() de votre formulaire CVT.

La fonction charger() est identique à celle d’un formulaire CVT conventionnel : elle doit retourner un tableau de tous les champs qui seront saisis dans l’ensemble du formulaire (donc toutes étapes confondues, comme si il n’y avait qu’une seule page de saisie).

Mais en plus, elle doit déclarer que le formulaire comporte plusieurs pages. Cela se fait en renvoyant en plus une valeur ’_etapes’ qui désigne le nombre d’étapes de saisies.

Dans notre exemple :

function formulaires_inscription_charger_dist() {
   return array (
        'email' => '',  // etape 1
        'nom' => '',  // etape 2
        'prenom' => '',
        'semaine' => 0, // étape 3
        '_etapes' => 3);
}

C’est cette valeur _etapes qui va déclencher la prise en charge par SPIP des différentes pages préparées ci-dessus.

Remarque : la fonction charger n’est pas appelée seulement pour la première étape, mais aussi pour initier l’affichage de chaque étape.

Vérifier la saisie à chaque étape

La vérification de la saisie présente ici une particularité. Au lieu d’avoir une seule fonction verifier() comme dans un formulaire CVT conventionnel, il va falloir fournir ici une fonction verifier() par page de saisie. Celles-ci sont numérotées à partir de 1 comme pour les squelettes des différentes pages.

formulaires_inscription_verifier_1_dist vérifie les saisies de l’étape 1 uniquement.
formulaires_inscription_verifier_2_dist vérifie les saisies de l’étape 2.
formulaires_inscription_verifier_3_dist vérifie les saisies de l’étape 3.
etc.

À l’intérieur de ces fonctions, l’appel à _request permet d’accéder aux valeurs saisies depuis l’étape 1 jusqu’à l’étape courante.

Le numéro d’étape courante et le nombre totale d’étapes sont également accessible par _request(’_etape’) et par _request(’_etapes’), si nécessaire, pour mutualiser du code par exemple.

Après chaque page n, SPIP appelle les fonctions de vérification des étapes 1 à n pour vérifier l’absence de régression dans la validation (qui pourrait être due à une erreur ou à une tentative de fraude par l’utilisateur). En cas d’erreur, l’utilisateur est automatiquement renvoyé sur la première page dont la saisie n’est pas correcte.

En cas de succès, SPIP passe à l’étape suivante, sauf si l’utilisateur est arrivé à la dernière page, auquel cas SPIP appelle la fonction traiter().

S’il y a une erreur, $erreurs['message_erreur'] n’est pas pris en compte et on ne peut donc pas spécifier une erreur globale au formulaire. Il faut déclarer une erreur spécifique au champ qui a levé l’erreur, avec $erreurs['champquivamal'] = "Message d'erreur...".

Normalisation

Certaines fonctions de vérification peuvent fournir une valeur normalisée via leur 3eme argument passé en référence.
-  Dans un formulaire CVT en une seule étape, il arrive qu’on normalise la valeur saisie à l’intérieur de la fonction ’verifier’ du formulaire elle-même, par un set_request.
-  Dans un formulaire multi-étape, il faut tenir compte du fait que la valeur normalisée sera de nouveau testée lors de l’étape suivante : elle doit donc aussi être acceptée par la fonction de vérification. Et si on retourne en arrière, cette valeur normalisée doit aussi pouvoir être affichée correctement par le squelette. Si ces 2 conditions ne sont pas réunies, c’est dans le ’traiter’ associé au formulaire qu’il faut normaliser les valeurs, et non dans le ’verifier’.

Exemple : la fonction de vérification des dates peut les normaliser sous forme de datetime, mais elle n’accepte pas les dates en format datetime. La valeur normalisée ne devra donc être utilisée que dans le ’traiter’.

Traiter la saisie

La fonction de traitement des saisies du formulaire n’est appelée que lorsque toutes les pages ont été saisies sans erreur.

Elle peut accéder à l’ensemble des saisies avec la fonction _request comme si le formulaire avait été saisi en une seule fois.

La fonction de traitement est donc tout à fait identique à celle d’un formulaire en une page et se nomme classiquement (ici formulaires_inscription_traiter_dist()).

Lorsque la dernière étape d’une saisie valide a été traitée, c’est encore une fois le squelette de cette étape qui est utilisé pour afficher le message retourné et confirmer que la saisie a bien été prise en compte.

Sans oublier...

-  Ce formulaire ainsi construit bénéficie de tous les avantages des formulaires CVT. Il suffit donc de l’encapsuler dans une <div class='ajax'> pour qu’il soit automatiqent pris en charge et permette la saisie multi-page en ajax.

-  Il est possible d’appeler le formulaire en commençant directement à l’étape 5, par exemple. Pour cela, il suffit de passer le paramètre "_etape=5" dans l’environnement (dans l’url par exemple, ou au moyen de set_request).
Dans ce cas, les vérifications des 4 pages précédentes sont effectuées et en cas de validation, l’étape 5 est affichée. Sinon c’est la première étape qui présente une erreur qui est affichée.

Auteur JLuc Publié le : Mis à jour : 06/07/23

Traductions : français, Nederlands