Utiliser les formulaires dans les applications
Une fois que vous avez créé un formulaire à l’aide du Form Builder ou converti un formulaire HTML Form Entry existant, vous devrez l’intégrer dans votre application. Le React Form Engine offre des moyens flexibles de rendre les formulaires dans différents contextes, des espaces de travail du dossier patient aux applications personnalisées.
Vue d’ensemble
Le React Form Engine peut être utilisé de deux manières principales :
- Extension Form Renderer - Un composant pré-construit qui gère le chargement des formulaires, le rendu et l’intégration dans les espaces de travail. C’est le moyen le plus simple de rendre les formulaires dans les espaces de travail.
- Composant FormEngine - Le composant principal qui offre un contrôle total sur le rendu des formulaires, la soumission et le comportement.
Rendre les formulaires dans les espaces de travail
Le dossier patient fournit déjà un espace de travail de saisie de formulaire via @openmrs/esm-patient-forms-app. Pour la plupart des flux du dossier patient, lancez patient-form-entry-workspace avec un objet formulaire et, si nécessaire, les détails de la rencontre au lieu d’enregistrer votre propre espace de travail :
import { launchWorkspace2 } from '@openmrs/esm-framework';
import { type Form } from '@openmrs/esm-patient-common-lib';
function launchMyForm(form: Form, encounterUuid?: string) {
launchWorkspace2('patient-form-entry-workspace', {
form,
encounterUuid,
additionalProps: {
mode: encounterUuid ? 'edit' : 'enter',
},
});
}patient-form-entry-workspace lit patient, patientUuid, visitContext et mutateVisitContext depuis le groupe d’espace de travail du dossier patient. Lancez-le depuis le dossier patient, ou créez votre propre enveloppe d’espace de travail si le formulaire doit s’exécuter en dehors de ce contexte.
Cet espace de travail encapsule le formulaire dans Workspace2, rend le visit-context-header-slot, puis rend soit un iframe HTML Form Entry, soit le React Form Engine via le form-widget-slot.
Créer un espace de travail de formulaire personnalisé
L’extension react-form-engine-widget est enregistrée par @openmrs/esm-form-engine-app dans le slot form-widget-slot. Vous n’avez besoin d’un espace de travail personnalisé que si vous voulez une enveloppe d’espace de travail différente, un comportement d’actualisation personnalisé ou un contexte de rendu hors du dossier patient.
Si vous créez votre propre espace de travail pour le dossier patient, enregistrez-le avec les routes Workspace v2 et placez sa fenêtre dans le groupe patient-chart :
{
"workspaces2": [
{
"name": "my-form-workspace",
"component": "myFormWorkspace",
"window": "my-form-window"
}
],
"workspaceWindows2": [
{
"name": "my-form-window",
"group": "patient-chart",
"width": "extra-wide",
"canMaximize": true
}
]
}Rendez ensuite form-widget-slot depuis une enveloppe Workspace2 et transmettez l’état attendu par le renderer de formulaire :
import React, { useState } from 'react';
import { ExtensionSlot, Workspace2 } from '@openmrs/esm-framework';
import { useSWRConfig } from 'swr';
import {
invalidateVisitAndEncounterData,
type PatientWorkspace2DefinitionProps,
type FormRendererProps,
} from '@openmrs/esm-patient-common-lib';
interface MyFormWorkspaceProps {
formUuid: string;
encounterUuid?: string;
}
export function MyFormWorkspace({
closeWorkspace,
workspaceProps: { formUuid, encounterUuid },
groupProps: { patient, patientUuid, visitContext, mutateVisitContext },
}: PatientWorkspace2DefinitionProps<MyFormWorkspaceProps, object>) {
const { mutate: globalMutate } = useSWRConfig();
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const state: FormRendererProps = {
formUuid,
patient,
patientUuid,
encounterUuid: encounterUuid ?? '',
visit: visitContext,
visitUuid: visitContext?.uuid,
closeWorkspace,
closeWorkspaceWithSavedChanges: () => {
mutateVisitContext?.();
invalidateVisitAndEncounterData(globalMutate, patientUuid);
return closeWorkspace({ discardUnsavedChanges: true });
},
setHasUnsavedChanges,
additionalProps: {
mode: encounterUuid ? 'edit' : 'enter',
},
};
return (
<Workspace2 title="Mon formulaire" hasUnsavedChanges={hasUnsavedChanges}>
<ExtensionSlot name="form-widget-slot" state={state} />
</Workspace2>
);
}closeWorkspaceWithSavedChanges fait partie de l’état FormRendererProps transmis à form-widget-slot. Utilisez-le pour actualiser les données après l’enregistrement avant de fermer l’espace de travail. Le closeWorkspace de Workspace v2 continue de gérer les annulations ou fermetures ordinaires.
Lancez l’espace de travail personnalisé avec Workspace v2 :
import { launchWorkspace2 } from '@openmrs/esm-framework';
function launchMyCustomWorkspace(formUuid: string) {
launchWorkspace2('my-form-workspace', {
formUuid,
});
}Cet exemple de lancement suppose qu’il s’exécute depuis une extension ou une page du dossier patient, afin que les props du groupe patient-chart soient disponibles pour l’espace de travail.
L’extension form renderer gère automatiquement le chargement du schéma de formulaire, les états d’erreur et la gestion du cycle de vie de l’espace de travail. C’est l’approche recommandée pour la plupart des cas d’usage.
Utiliser FormEngine directement
Pour plus de contrôle sur le rendu et le comportement des formulaires, vous pouvez utiliser le composant FormEngine directement depuis @openmrs/esm-form-engine-lib. C’est utile lorsque vous avez besoin d’une gestion personnalisée de la soumission, souhaitez rendre les formulaires en dehors des espaces de travail, ou avez besoin d’un contrôle précis sur le comportement du formulaire.
Utilisation de base
import React from 'react';
import { type Encounter } from '@openmrs/esm-framework';
import { FormEngine, type FormSchema } from '@openmrs/esm-form-engine-lib';
interface MyFormComponentProps {
patientUuid: string;
formSchema: FormSchema;
}
export function MyFormComponent({ patientUuid, formSchema }: MyFormComponentProps) {
const handleSubmit = (encounters: Array<Encounter>) => {
console.log('Formulaire soumis :', encounters);
// Gérer la soumission du formulaire
};
return (
<FormEngine
patientUUID={patientUuid}
formJson={formSchema}
onSubmit={handleSubmit}
/>
);
}Charger le schéma de formulaire depuis l’UUID
Si vous avez un UUID de formulaire au lieu du schéma, transmettez-le à la prop formUUID. Le FormEngine chargera automatiquement le schéma :
import React from 'react';
import { FormEngine } from '@openmrs/esm-form-engine-lib';
interface MyFormComponentProps {
patientUuid: string;
formUuid: string;
}
export function MyFormComponent({ patientUuid, formUuid }: MyFormComponentProps) {
return (
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
/>
);
}Le FormEngine gère les états de chargement et les erreurs en interne. Vous n’avez pas besoin de récupérer manuellement le schéma du formulaire sauf si votre cas d’usage l’exige.
Props et configuration du formulaire
Le composant FormEngine accepte les props suivantes :
Props requises
patientUUID(string) - L’UUID du patient pour lequel le formulaire est rempli
Props optionnelles
formUUID(string) - L’UUID du formulaire à charger depuis le serveur. Si fourni, le schéma du formulaire sera chargé automatiquement. Ne peut pas être fourni avecformJson: vous devez utiliser soitformUUID, soitformJson, mais pas les deux.formJson(FormSchema) - L’objet schéma de formulaire. Utilisez-le lorsque vous avez déjà le schéma chargé ou souhaitez utiliser un schéma personnalisé.encounterUUID(string) - L’UUID d’une rencontre existante à modifier. Lorsqu’il est fourni, le formulaire sera pré-rempli avec les données de la rencontre et rendu en mode édition.visit(Visit) - L’objet visite à associer à la rencontre soumise. L’espace de travail de formulaire du dossier patient fournit la visite active pour les nouveaux formulaires, ou la visite de la rencontre lorsque vous modifiez une rencontre existante.mode('enter' | 'edit' | 'view' | 'embedded-view') - Le mode de rendu du formulaire. Voir Modes de rendu des formulaires ci-dessous.formSessionIntent(string) - L’intention de formulaire utilisée lors de l’affinage du schéma. Elle applique les valeurs et comportements propres à une intention, commeavailableIntents.defaultPage, les champsreadonly, les champshide, lesdefaultValuede champs et la sélection d’intention des sous-formulaires. L’extension form renderer transmet'*'par défaut; lorsque vous utilisezFormEnginedirectement, transmettez'*'explicitement si vous voulez le comportement d’intention générique.onSubmit(function) - Fonction de rappel appelée lorsque le formulaire est soumis avec succès. Reçoit un tableau de résultats de processeur. Pour les formulaires qui utilisentEncounterFormProcessor, ces résultats sont les rencontres créées ou mises à jour.onCancel(function) - Fonction de rappel appelée lorsque l’utilisateur annule le formulaire.handleClose(function) - Fonction de rappel appelée lorsque le formulaire doit être fermé.handleConfirmQuestionDeletion(function) - Gestionnaire personnalisé pour confirmer la suppression de questions répétables. Doit retourner une Promise qui se résout lorsque la suppression est confirmée.markFormAsDirty(function) - Fonction de rappel appelée lorsque l’état “dirty” du formulaire change. Utile pour l’intégration dans les espaces de travail pour demander confirmation avant de fermer.hideControls(boolean) - Masquer les boutons d’action du formulaire (Enregistrer, Annuler). Utile pour les vues intégrées ou l’interface utilisateur personnalisée.hidePatientBanner(boolean) - Masquer la bannière patient qui apparaît dans les espaces de travail ultra-larges.preFilledQuestions(Record<string, string | number | Date | boolean | Array<string>>) - Pré-remplir des questions spécifiques avec des valeurs. Les clés sont les IDs des questions, les valeurs sont les valeurs pré-remplies.
Combinaisons de props courantes
Formulaire de base avec UUID :
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
/>Modification d’une rencontre existante :
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
encounterUUID={encounterUuid}
mode="edit"
/>Formulaire avec intégration dans un espace de travail :
import React, { useState } from 'react';
import { Workspace2, type Workspace2DefinitionProps } from '@openmrs/esm-framework';
import { FormEngine } from '@openmrs/esm-form-engine-lib';
function MyDirectFormWorkspace({
closeWorkspace,
workspaceProps: { patientUuid, formUuid },
}: Workspace2DefinitionProps<{ patientUuid: string; formUuid: string }>) {
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
return (
<Workspace2 title="Mon formulaire" hasUnsavedChanges={hasUnsavedChanges}>
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
onSubmit={() => closeWorkspace({ discardUnsavedChanges: true })}
handleClose={() => closeWorkspace()}
markFormAsDirty={setHasUnsavedChanges}
/>
</Workspace2>
);
}Modes de rendu des formulaires
Le React Form Engine prend en charge quatre modes de rendu, chacun adapté à différents cas d’usage :
Mode Enter (par défaut)
Mode : 'enter' ou undefined
Cas d’usage : Créer de nouvelles entrées de formulaire
Comportement :
- Le formulaire est rendu en mode lecture-écriture
- Tous les champs sont modifiables
- Le formulaire peut être soumis pour créer une nouvelle rencontre
- Sélectionné automatiquement lorsqu’aucun
encounterUUIDn’est fourni et quemoden’est pas spécifié
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
mode="enter" // ou omettre pour la valeur par défaut
/>Mode Edit
Mode : 'edit'
Cas d’usage : Modifier des entrées de formulaire existantes
Comportement :
- Le formulaire est rendu en mode lecture-écriture
- Le formulaire est pré-rempli avec les données de la rencontre existante
- Le formulaire peut être soumis pour mettre à jour la rencontre
- Sélectionné automatiquement lorsque
encounterUUIDest fourni et quemoden’est pas spécifié
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
encounterUUID={encounterUuid}
mode="edit" // ou omettre lorsque encounterUUID est fourni
/>Mode View
Mode : 'view'
Cas d’usage : Afficher les données du formulaire en mode lecture seule
Comportement :
- Le formulaire est rendu en mode lecture seule
- Tous les champs sont désactivés
- Le formulaire ne peut pas être soumis
- L’enregistrement est désactivé ou masqué, et le contrôle fermer/annuler ferme le formulaire
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
encounterUUID={encounterUuid}
mode="view"
/>Mode Embedded View
Mode : 'embedded-view'
Cas d’usage : Afficher les données du formulaire dans un widget ou une carte condensée
Comportement :
- Le formulaire est rendu en mode lecture seule
- La navigation latérale et les boutons d’action du bas sont masqués
- La bannière patient est masquée
- Les champs transitoires vides, ainsi que les champs vides configurés pour être masqués dans les formulaires en lecture seule, sont omis
- Mise en page compacte adaptée à l’intégration dans d’autres composants
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
encounterUUID={encounterUuid}
mode="embedded-view"
hideControls={true}
/>Gestion de la soumission et de la réponse du formulaire
Lorsqu’un formulaire est soumis, le callback onSubmit reçoit un tableau de résultats de processeur. Pour les formulaires qui utilisent EncounterFormProcessor, chaque résultat est une rencontre créée ou mise à jour.
Gérer la soumission du formulaire
import { type Encounter } from '@openmrs/esm-framework';
function MyFormWorkspace({ patientUuid, formUuid }: Props) {
const handleSubmit = (encounters: Array<Encounter>) => {
const encounter = encounters[0];
// Gérer la soumission réussie
console.log('Rencontre créée :', encounter.uuid);
console.log('Observations :', encounter.obs);
// Fermer l'espace de travail ou naviguer
closeWorkspace({ discardUnsavedChanges: true });
// Actualiser ici les données liées aux rencontres, visites ou espaces de travail.
};
return (
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
onSubmit={handleSubmit}
/>
);
}Gestion des erreurs
Le Form Engine gère automatiquement les erreurs de validation et les affiche en ligne. Le callback onSubmit est appelé uniquement après une soumission réussie. Si la soumission échoue, le Form Engine gère l’erreur en interne et l’affiche à l’utilisateur. Votre callback onSubmit n’est alors pas appelé.
import { type Encounter } from '@openmrs/esm-framework';
function MyFormWorkspace({ patientUuid, formUuid }: Props) {
const handleSubmit = (encounters: Array<Encounter>) => {
// Ce callback est appelé uniquement si la soumission réussit
// Le Form Engine gère les erreurs en interne
console.log('Formulaire soumis avec succès :', encounters);
closeWorkspace({ discardUnsavedChanges: true });
};
return (
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
onSubmit={handleSubmit}
/>
);
}Exemple complet : Espace de travail de formulaire
Voici un exemple complet d’un espace de travail de formulaire personnalisé qui s’intègre au dossier patient :
import React, { useMemo, useState } from 'react';
import { ExtensionSlot, Workspace2 } from '@openmrs/esm-framework';
import { useSWRConfig } from 'swr';
import {
invalidateVisitAndEncounterData,
type FormRendererProps,
type PatientWorkspace2DefinitionProps,
} from '@openmrs/esm-patient-common-lib';
interface MyFormWorkspaceProps {
formUuid: string;
encounterUuid?: string;
}
export function MyFormWorkspace({
closeWorkspace,
workspaceProps: { formUuid, encounterUuid },
groupProps: { patient, patientUuid, visitContext, mutateVisitContext },
}: PatientWorkspace2DefinitionProps<MyFormWorkspaceProps, object>) {
const { mutate: globalMutate } = useSWRConfig();
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const state = useMemo(
(): FormRendererProps => ({
formUuid,
patient,
patientUuid,
visit: visitContext,
visitUuid: visitContext?.uuid,
encounterUuid: encounterUuid ?? '',
closeWorkspace,
closeWorkspaceWithSavedChanges: () => {
mutateVisitContext?.();
invalidateVisitAndEncounterData(globalMutate, patientUuid);
return closeWorkspace({ discardUnsavedChanges: true });
},
setHasUnsavedChanges,
additionalProps: {
mode: encounterUuid ? 'edit' : 'enter',
},
}),
[
formUuid,
globalMutate,
patient,
patientUuid,
visitContext,
encounterUuid,
closeWorkspace,
mutateVisitContext,
setHasUnsavedChanges,
]
);
return (
<Workspace2 title="Mon formulaire" hasUnsavedChanges={hasUnsavedChanges}>
<ExtensionSlot name="form-widget-slot" state={state} />
</Workspace2>
);
}Pré-remplir les questions du formulaire
Vous pouvez pré-remplir des questions spécifiques dans un formulaire en utilisant la prop preFilledQuestions :
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
preFilledQuestions={{
'vitals-weight': 70,
'vitals-height': 175,
'chief-complaint': 'Le patient signale un mal de tête'
}}
/>Les clés dans preFilledQuestions doivent correspondre à la propriété id des questions dans votre schéma de formulaire. Lorsque vous transmettez des valeurs via l’extension form renderer du dossier patient, conservez-les sous forme de chaînes, car son type partagé FormRendererProps limite actuellement preFilledQuestions à Record<string, string>.
Intention de session de formulaire
La prop formSessionIntent sélectionne les comportements propres à une intention dans le schéma de formulaire. Utilisez-la lorsqu’un schéma définit des valeurs par défaut, des champs en lecture seule ou masqués, des pages par défaut ou des comportements de sous-formulaires différents selon les workflows. L’extension form renderer du dossier patient utilise '*' par défaut, mais l’utilisation directe de FormEngine laisse cette valeur vide sauf si vous la transmettez :
<FormEngine
patientUUID={patientUuid}
formUUID={formUuid}
formSessionIntent="VITALS" // Appliquer les comportements du schéma pour l'intention VITALS
/>Prochaines étapes
- Découvrez comment créer des formulaires avec le Form Builder
- Lisez la documentation du React Form Engine pour les fonctionnalités avancées
- Consultez la documentation des espaces de travail pour en savoir plus sur la création d’espaces de travail