Conception d’un formulaire

Principes généraux

La réalisation d’un formulaire et de ses effets post validation reposent :

  1. sur un modèle de données bien conçu.
  2. sur un formulaire rédigé dans les règles
  3. sur de possibles interactions entre champs de donnée via javascript
  4. sur un traitement post validation / prégénération PDF via class PHP propre au module

Élaboration du modèle de données

Le modèle de données se créer dans Configuration > Modèles des données > Données médicales.

Il est conseillé de créer une catégorie par formulaire envisagé et d’y ranger chaque type créé.

Découper l’information à recueillir avec précision

Il convient d’être parfaitement spécifique dans la création et l’utilisation d’un type de donnée. Par exemple, ne créez pas un champ "Longueur Cranio-Caudale" (LCC) en pensant l’utiliser quel que soit le type d’examen (écho 12 SA, écho 22 SA ...) et quel que soit le foetus. La bonne pratique est de faire un champ LCC écho 12 SA foetus A puis un autre pour le foetus B et ainsi de suite pour chaque examen.

Choix du type de champ

La clef d’un formulaire efficace est aussi le choix du type de champ utilisé. Les types utilisables sont :

Nom interne

A la création d’un nouveau type, il faut spécifier un nom interne. Il doit être unique dans le système. Les caractères utilisés doivent être alphanumériques, sans espace, sans accent ([a-zA-Z0-9_]*). Soignez ce choix. Préfixez-le éventuellement d’une chaîne qui vous identifie.

Réponse par défaut

Le choix par défaut permet de pré remplir le champ avec du contenu qui pourra être modifié avant validation.

Notez bien que les champs de type select ne peuvent recevoir de réponse non prévue quand l’utilisateur les remplit : il convient donc que toutes les réponses soient proposées pour qu’il n’y ait pas d’impasse côté utilisateur.
Pour spécifier les choix du menu select, utilisez le champ réponse par défaut en adoptant un syntaxe yaml :

'doulpelv' : 'douleurs pelviennes'
'doulfid' : 'douleurs FID'
'doulfig' : 'douleurs FIG'
'dyspareunies' : 'dyspareunies'
'suspiendomet' : 'suspicion d'endométriose'
'bilaninfer' : 'bilan d'infertilité'
'suivipma' : 'suivi PMA'


Suivant le cas, vous pouvez ajouter si besoin un choix vierge en tête de menu en utilisant quelque chose comme

'Z' : ''

Ne changez JAMAIS le couple ’clé’ : ’label du menu’ quand un type de données a déjà été utilisé ! Vous perdriez toute liaison entre l’information stockée et sa signification !

Règles de rédaction du formulaire

NB : Les formulaires d’affichage, contenus dans la catégorie du même nom, répondent à des règles simplifiées expliquées plus bas dans cet article.

Règles de base

Les formulaires se rédigent en respectant une syntaxe yaml. L’indentation d’une ligne à l’autre pour spécifier qu’un élément est contenu dans un autre est de 2 espaces supplémentaires en début de ligne par rapport au niveau supérieur.

Le premier niveau est structure: .

Lignes et colonnes

Imbriquer lignes et colonnes

Chaque questionnaire doit être pensé en termes de lignes et de colonnes. Notez bien qu’une colonne ne peut contenir de ligne. C’est une limitation actuelle de l’interpréteur qui construit le formulaire html à partir de votre rédaction yaml.

Une ligne fait 12 de large. Ceci est fixé, non modifiable, lié à l’utilisation de Bootstrap. Chaque colonne qui est ajoutée à une ligne peut donc faire une taille comprise entre 1 et 12. Tant que la somme des tailles des colonnes d’une ligne n’est pas égale à 12, on peut ajouter encore d’autres colonnes. Si on dépasse le nombre de 12, on s’expose à des problèmes d’affichage imprévisibles.

Chaque ligne est numérotée en commençant par 1 : row1, row2, row3 ... Indiquez 2 fois un même numéro de ligne expose à des problèmes imprévisibles d’affichage.
Chaque colonne doit être numérotée dans sa ligne : col1, col2 ...

structure:
 row1:
   col1:
   col2:
   ....
 row2:
   col1:
   ...
Paramètres pour les lignes

Un titre de ligne peut être spécifié via head: 'titre de ligne'.
Une class CSS spécifique à la ligne peut être ajoutée via class: 'maClassCss' (ce qui permet par exemple des interactions javascript).

structure:
 row1:                              
   class: 'maClassCss maClassCss2'
   head: Un titre de ligne'    
   col1:
Paramètres pour les colonnes

Un titre de colonne peut être spécifié via head: 'titre de colonne'.

La largeur de colonne est spécifiée via size: X ou X est un nombre de 1 à 12 (cf plus haut) ou une ou des class bootstrap (col- ...).

À partir de la version 5.3.0, on peut aussi spécifier class: pour ajouter un nom de class CSS à une colonne.

Les champs de recueil de données à inclure dans la colonne sont passés dans bloc:. Ils apparaîtront dans l’ordre indiqué, chacun prenant la pleine largeur de la colonne parente. Il peuvent être indiqué en valeur numérique, mais à partir de la version 3.0.0, à la validation du formulaire, ils seront automatiquement convertis pour indiquer le nom du champ. Notez que le code du formulaire est également automatiquement commenté depuis la version 3.0.0.

 ...
 row3:                              
   col1:                              
     head: 'Titre de colonne'    
     size: 'col-3'
     class: 'classPerso'     (v5.3.0)
     bloc:                          
       - birthname                        
       - lastname          
       - firstname  
   col2:                              
   ...

On peut également inclure du texte brut en lieu et place d’un bloc ou inclure un template Twig pour, par exemple, insérer une image, un SVG ou tout autre élément dans le questionnaire :

 ...
 row3:                              
   col1:                              
     size: col-12 col-sm-4
     bloc:                          
       - birthname                        
       - label{Mon texte brut}
       - template{schemaRachis}    
   col2:                              
   ...

Ici le template recherché et inséré sera alors schemaRachis.html.twig.

À partir de la v5.8, on peut spécifier des class pour label

 ...
 row3:                              
   col1:                              
     size: col-12 col-sm-4
     bloc:                          
       - birthname                        
       - label{Mon texte brut},class={font-weight-bold text-warning}

Paramétrage de chaque élément d’une colonne

Indépendamment de leur définition dans le modèle de données, chaque champ de recueil peut subir des modifications au niveau du formulaire. Ces modifications sont indiquées après l’identifiant du type de donnée et séparées par des virgules (sans espaces).

Paramètres communs
Paramètres pour champ de type text, number, select
Paramètres pour champ de type textarea
Paramètres pour champ de type text
Paramètres pour champ de type number
Paramètres pour champ de type radio

Actions globales sur / via le formulaire

Ajout d’une class

Il est possible de préciser l’attribut class du formulaire créé de la façon suivante :

global:
 formClass: 'class1 class2'

structure:
 row1:
   col1:
   ...
Ignorer le retour ajax

L’ajout de la class ignoreReturn permet d’ignorer les données générées par la requête ajax et ainsi de ne pas rafraîchir les historiques dans le dossier patient à l’enregistrement d’un nouveau formulaire de consultation.

Titrer automatiquement les éléments des historiques

Il est possible (version 4.1.0) de définir quel champ du formulaire servira de titre complémentaire à la ligne générée par le formulaire dans les historiques du dossier patient.

Dans l’exemple ci-dessous, c’est le texte entré dans conclusionCsAdulte qui sera utilisé.

global:
 autoTitle: 'conclusionCsAdulte'

structure:
   ...
Dater automatiquement les éléments des historiques

Il est possible (version 5.4.0) de définir quel champ du formulaire servira à dater de façon effective la ligne générée par le formulaire dans les historiques du dossier patient. Ce changement de date correspond à celui qui peut être fait manuellement sur la ligne d’historique.

Dans l’exemple ci-dessous, c’est la date entrée dans dateDePriseEnCompte qui sera utilisée.

global:
 autoDate: 'dateDePriseEnCompte'

structure:
   ...

Interactions entre champs d’un formulaire via JavaScript

Depuis la version 5 de MedShakeEHR, le JavaScript concernant un formulaire peut être renseigné ou édité dans la zone d’édition de ce formulaire en zone de Configuration. La méthode précédente décrite ci-dessous (fichier externe) est dépréciée, mais toujours fonctionnelle.

Concernant l’interaction, il est fortement conseillé de sélectionner les champs du formulaire en fonction de son id ou de data-internalName. L’utilisation d’index numérique est à bannir depuis la v3.0.0.

Méthode dépréciée :

Chaque formulaire affiché sur l’écran de l’utilisateur appelle un fichier JavaScript situé dans public_html/js/module/formsScripts/.

Ce fichier est nommé par le nom interne du formulaire pour lequel il agit (et une extension .js).
Des fonctions communes peuvent également être stockées dans public_html/js/module/common*NomModule*.js.

Sauvegarder les données : alternative pour les champs vides

À la conception du formulaire de consultation, il faut indiquer l’URL de destination quand la validation sera demandée par l’utilisateur.
L’URL par défaut est /patient/ajax/saveCsForm/.
Dans ce mode, les champs laissés vides sont sauvegardés ... vides ! Il peut paraître étrange de sauvegarder du vide, mais l’absence de réponse est aussi une forme de réponse dans de nombreux cas !
Ce comportement par défaut peut parfois poser problème, en particulier si votre formulaire de consultation contient des dizaines, voire des centaines de lignes ou de variables cachées. Deux solutions s’offrent à vous.

Modifier le comportement global

Il conviendra dans ce cas d’utiliser l’URL /patient/ajax/saveCsForm/ignoreEmpty/. Seuls les éléments contenant une valeur non vide ( !=trim($valeur)) seront alors enregistrés en base.

Modifier le comportement champ par champ

Vous pouvez utiliser pour cela donotsaveempty (v5.6.0) comme paramètre du champ concerné (voir plus haut).

Comportement à l’édition

Notez qu’en cas d’édition de la consultation et de modification d’une valeur préalablement remplie et devenue vide, un enregistrement vide sera fait pour signer ce cas de figure pour les versions antérieures à 5.6.0.
À partir de la version 5.6.0, la version précédente sera simplement marquée "effacée", le champ retrouvant de facto une valeur vide.

Traitement post validation / prégénération PDF via class PHP propre au module

Les modifications suggérées ci-dessous touchent au module de MedShakeEHR. Nous vous suggérons de ne pas modifier seul de votre côté ces fonctions, mais de proposer une modification des sources de l’application (Github) afin qu’elles soient incluses à la prochaine version.

Pour plus d’informations, considérez l’article Création d’un nouveau module.

Traitement post validation / pré sauvegarde propre au module

class/msMod*NomModule*DataSave.php permet de traiter chaque type de données avant son insertion en base de données. Attention, il n’y a pas ici de gestion d’erreur, mais un simple formatage la plupart du temps.

Calculs médicaux propres au module

Les calculs médicaux propres au module utilisé sont disponibles dans class/msMod*NomModule*CalcMed.php.

Préparation à la génération de courriers

class/msMod*NomModule*DataCourrier.php permet de déclencher des mécanismes pour l’obtention de données complémentaires quand un type particulier de données est passé au système pour impression.

Spécificités des formulaires d’affichage

Les formulaires contenus dans la catégorie "Formulaires d’affichage" ont un rôle et un fonctionnement spécifiques.
Ils ont pour but de décrire les colonnes d’un tableau à générer, principalement ceux des résultats de recherche patient ou praticien.
Le critère de ligne n’ayant rien à faire dans ce contexte, la syntaxe d’écriture en yaml est simplifiée.

col1:
   head: "Activité pro"
   bloc:
       - job                                                     
col2:
   head: "Tel"
   bloc:
       - telPro,click2call                      
col3:
   head: "Fax"
   bloc:
       - faxPro                                            
col4:
   head: "Email"
   blocseparator: " - "
   bloc:
       - emailApicrypt                            
       - personalEmail                          

Chaque colonne contient donc une information head qui servira de titre à la colonne.
Chaque colonne contient un ou plusieurs blocs.
Chaque bloc peut recevoir un ou plusieurs noms de class à appliquer, chaque nom étant ajouté après l’information précédente, séparé par une virgule.
Quand l’information correspondant à 2 blocs ou plus sera affichée dans une colonne (ici par exemple emailApicrypt et personalEmail pour la colonne 4), il est possible de définir un séparateur à afficher entre les 2 données via blocseparator.