Créer des formulaires accessibles avec Angular

Creating Accessible Forms with Angular

Lors de la recherche d'exemples de formulaires angulaires et de leur configuration, nous avons remarqué une tendance qui peut avoir été transférée à partir d'exemples AngularJS : une approche suggérée lors de la conception et du développement de formulaires pour inclure la validation en ligne et réserver le contrôle de soumission dans un état désactivé . tant que des données valides n'ont pas été saisies. Bien que ce paradigme puisse sembler plus moderne et puisse aider l'utilisateur à remplir le formulaire avec succès, quelques problèmes d'utilisabilité et d'accessibilité apparaissent lors de la mise en œuvre de ce flux de travail.

Nous explorerons ces concepts en profondeur, discuterons des raisons pour lesquelles ils pourraient ne pas être la meilleure solution pour vos utilisateurs et proposerons des solutions pratiques et plus inclusives qui peuvent être implémentées dans vos formulaires angulaires.

Lors de l'examen des exemples d'approches fournis, nous observons deux tendances en particulier : encourager la validation en ligne de chaque contrôle de formulaire après qu'il a été "touché" (essentiellement lorsque l'utilisateur s'éloigne de l' input ) et maintenir le bouton d'envoi dans un état disabled jusqu'à ce que chaque test de validation a été satisfait.

Validation en ligne

Nous recommandons généralement de ne pas utiliser la validation en ligne, car cette méthode peut parfois causer un peu de confusion ou de frustration à l'utilisateur. Voici quelques exemples illustrant cela :

  • Lorsqu'une personne utilisant un lecteur d'écran navigue dans un formulaire pour obtenir un aperçu du terrain, essayant de lire ce que sont chaque champ et les données attendues
  • Quelqu'un qui pourrait vouloir remplir des champs dans un ordre différent
  • Quand quelqu'un quitte un champ pour aller chercher quelque chose pour être certain des données à placer dans le contrôle de formulaire

Ces actions simples déclenchent le message d'erreur et le résultat peut être assez irritant.

Dans nos propres études d'utilisabilité, les gens grognent ou jurent souvent à haute voix lorsque des messages d'erreur apparaissent avant même d'avoir commencé à remplir des formulaires !

Des problèmes d'accessibilité supplémentaires apparaissent lorsque l'utilisateur quitte un champ ; le message d'erreur s'affiche visuellement mais pas sur la technologie d'assistance. Pour entendre le message d'erreur, l'utilisateur doit revenir en arrière dans le formulaire. Il s'agirait d'une action requise inattendue pour entendre les messages d'erreur.

État désactivé

Lorsque le bouton Soumettre est disabled par défaut, ce n'est qu'après que toutes les règles de validation du formulaire ont été satisfaites que le bouton Soumettre devient disponible. Cette mise en place peut entraîner une expérience utilisateur déroutante ou frustrante ; il n'y a aucune indication quant à la raison pour laquelle le bouton d'envoi serait désactivé après avoir rempli le formulaire.

Par conséquent, les boutons disabled peuvent présenter deux défis supplémentaires pour les particuliers :

  1. Les personnes malvoyantes peuvent ne pas être en mesure de percevoir le texte du bouton dans l'état grisé.
  2. Certaines technologies d'assistance ignorent les éléments désactivés ; les utilisateurs de lecteurs d'écran peuvent ne pas avoir une image complète de ce qui est disponible dans l'interface, ce qui entraîne un sentiment d'incertitude.

Exemple de formulaire

Dans l'exemple lié ci-dessous, nous avons un formulaire commun de style "Contactez-nous". Ce formulaire présente le flux de travail décrit ci-dessus, y compris les tendances de test de la validité des entrées après l'interaction avec le contrôle et le bouton d'envoi désactivé par défaut :

Dans les coulisses

Voici ce qui se passe dans le code pour que ce flux de travail actuel ait lieu :

Pour chaque contrôle input de formulaire nécessitant une validation, il existe une directive *ngIf . Cette directive teste deux conditions :

  1. Testez la condition de validation à l'aide de la contactForm.controls[name].hasError()
  2. Testez l'état du contrôle à l'aide de l' contactForm.controls[name].touched
 < div *ngIf= "contactForm.controls['firstName'].hasError('required') && contactForm.controls['firstName'].touched" > You must include a First Name. </ div >

Étant donné que chaque instruction de condition utilise la clause "et", les deux conditions doivent être remplies pour afficher le message d'erreur d'entrée. Fondamentalement, ces conditions indiquent : "Lorsque l'utilisateur s'éloigne du contrôle d' input , vérifiez la validité des données. Si les données ne sont pas valides, affichez le message d'erreur."

Le bouton Soumettre comporte la liaison de propriété [disabled]="!contactForm.valid" . Cette liaison maintient le bouton dans un état désactivé jusqu'à ce que les données du formulaire soient complètement valides. Ce n'est qu'alors que l'utilisateur pourra trouver et activer le bouton.

 < button type = "submit" [ disabled ]= "!contactForm.valid" > Submit </ button >

Prise en compte de l'accessibilité avec ce workflow

Pour atténuer certains de ces problèmes potentiels pour vos utilisateurs, nous vous recommandons d'adopter une approche complètement différente. Envisagez d'apporter les modifications suivantes à votre workflow de formulaire :

1) Autorisez la validation lors de la soumission initiale du formulaire en gardant le button de soumission activé. Cela permettra à l'utilisateur d'explorer facilement le formulaire et de se familiariser avec la structure du formulaire lors de la première exécution. Même si les champs du formulaire contiennent des erreurs, autorisez les utilisateurs à soumettre le formulaire selon leurs conditions, lorsqu'ils se sentent à l'aise de le faire. Pour ce faire, nous supprimons simplement la liaison de propriété [disabled] du bouton d' submit .

 < button type = "submit" > Submit </ button >

2) Ajoutez une nouvelle propriété de classe, submitted , qui servira de drapeau booléen. Par défaut, sa valeur sera false . Lorsque le bouton d'envoi du formulaire est cliqué, mettez à jour sa valeur sur true . Cette propriété sera utilisée dans le modèle dans le cadre de la directive *ngIf lors de la vérification de nos règles de validation et de l'affichage d'un message d'erreur.

 export class ContactFormComponent { submitted: boolean ; // … submitForm(value: any) { this .submitted = true ; // … } }

3) Lorsqu'une input est dans un état d'erreur, affichez le texte du message d'erreur dans son label correspondante. Cela servira de rappel de l'erreur et de la valeur attendue lors de la navigation vers le contrôle, ainsi que de tout autre contrôle dans un état d'erreur lorsque l'utilisateur avance dans le contenu du formulaire.

< label for = "firstName" > < input id= "firstName" type= "text" [formControl]= "contactForm.controls['firstName']" /> < div *ngIf= "contactForm.controls['firstName'].hasError('required') && submitted" > You must include a First Name. </div> </label>

Bonus : Cela a également l'avantage de créer une zone de clic/tapotement beaucoup plus grande pour les personnes qui utilisent une souris ou un appareil mobile, puisque les étiquettes elles-mêmes sont des cibles !

Nous pouvons vérifier si l'entrée est dans un état d'erreur en ajustant la directive *ngIf . Continuez à utiliser la méthode controls[name].hasError() pour tester la validité de la valeur d'entrée, mais supprimez l'indicateur controls[name].touched car nous n'avons plus besoin de cette propriété. C'est ici que nous pouvons utiliser la nouvelle propriété submitted pour voir si le formulaire a été soumis. Si la valeur input n'est pas valide et que le formulaire a été submitted , affichez le message d'erreur.

Boostez vos formulaires avec une accessibilité de niveau supérieur

Jusqu'à présent, nous avons résolu les problèmes de flux avec cette approche en supprimant l'état disabled du button d'envoi par défaut et en validant chaque entrée après la soumission initiale. Nous pouvons prendre quelques mesures supplémentaires pour augmenter considérablement l'accessibilité globale de tout formulaire volumineux/complexe. Pour éviter une ingénierie excessive, les formulaires courts tels qu'un formulaire de connexion seraient exemptés de ce qui suit :

1) S'il y a des erreurs à afficher, affichez chaque message d'erreur dans une liste ul en haut du formulaire, au-dessus des champs du formulaire. Lorsque cette liste est présentée visuellement, déplacez par programmation le focus du clavier vers le haut de la liste, de préférence un élément d'en-tête. Cela fournira une notification que quelque chose s'est passé après avoir cliqué sur le button soumettre , qu'il y a des erreurs à corriger et le nombre total d'erreurs (via le nombre d'éléments de la liste ul ). L'implémentation de chaque message d'erreur dans une liste aide les utilisateurs à comprendre puis à naviguer pour corriger les erreurs. Dans la méthode submitForm() , sélectionnez l'en-tête et appliquez focus() lorsque le formulaire renvoie invalide.

< ul id = "error-list" > < li * ngIf = "contactForm.controls['firstName'].hasError('required')" ></ li ></ ul >

2) Pour chaque message d'erreur dans la liste ul , implémentez le texte sous forme de lien qui pointe vers le contrôle input correspondant, en faisant correspondre sa valeur id avec l'attribut href du lien. Avec cela en place, les utilisateurs pourront entendre le texte du message d'erreur et avoir un raccourci directement vers l' input en question, ce qui est utile pour les utilisateurs ayant des problèmes de dextérité qui comptent sur le clavier.

< a href = "#firstName" > You must include a First Name </ a > <!-- … --> < input id = "firstName" type = "text" [ formControl ]= "contactForm.controls['firstName']" />

3) Assurez-vous que tous les champs obligatoires sont transmis à tous les utilisateurs en ayant un indicateur visuel "*" (requis) avec une alternative textuelle pour les utilisateurs de technologie d'assistance. Cela aidera tous les utilisateurs à comprendre quelles parties du formulaire doivent être remplies et lesquelles peuvent être ignorées. Cela pourrait même être une image SVG avec un texte alternatif !

 < span aria-hidden = "true" > * </ span > < span class = "visuallyhidden" > Required </ span >

Mettre tous ensemble

Voici à nouveau notre exemple de formulaire, mais avec les recommandations décrites ci-dessus :

Avec ces changements en place, toute personne qui compte sur une technologie d'assistance ou qui a besoin d'un peu plus de conseils pour remplir un formulaire aura une meilleure compréhension de la façon dont le formulaire est structuré et de l'état actuel du formulaire, s'il y a des erreurs et comment adressez-vous à eux. Si des modifications doivent être apportées lors de la soumission, l'accent sera mis sur la liste des erreurs. À partir de là, les liens d'erreur déplaceront le focus directement vers l' input de formulaire en question. À partir de ce moment, des messages d'erreur seront annoncés lors de la navigation dans le formulaire, et toute modification des données pourra facilement être effectuée avec une plus grande confiance de la part de l'utilisateur.

Gardez à l'esprit que ce flux de travail recommandé n'est pas spécifique aux formulaires angulaires. Les techniques et concepts explorés dans cet article peuvent être appliqués à n'importe quel formulaire, en utilisant n'importe quel framework ou bibliothèque JavaScript.

Angular est capable de prendre en charge les fonctionnalités d'accessibilité, mais les développeurs doivent encore s'assurer que l'implémentation répond aux besoins de tous les utilisateurs.

L'essentiel est de s'assurer que vos utilisateurs sont en mesure de découvrir la mise en page et les entrées du formulaire, et de terminer leur tâche de remplir le formulaire que vous avez conçu. Ils auront la confiance et l'assurance qu'ils ont fait ce qu'il fallait et que vos deux objectifs sont atteints !

Envisagez d'améliorer le flux de vos formulaires angulaires avec ces suggestions afin d'aider vos utilisateurs à remplir facilement les formulaires avec succès.

Retour au blog