E <      ^ R pdf    Documentation Xdepo > Guide d'implémentation >                

 

Utilisation de CForms avec Xdepo

2005-02-11 / 2005-02-27
Sévigny, Martin (AJLSM, France)
Delperier, Myriam (AJLSM, France)

Les formulaires permettant de modifier et saisie des documents XML dans Xdepo sont basés sur la technologie CForms du projet Apache Cocoon . Toutefois, afin de faciliter le développement de certains formulaires et pour permettre leur parfaite intégration dans l'environnement Xdepo, quelques consignes d'utilisation sont nécessaires. Ce document présente ces consignes ainsi que les principaux éléments CForms.

Nous encourageons vivement les lecteurs qui souhaitent développer leur propres formulaires de consulter la documentation CForms de Cocoon ainsi que les exemples livrés avec cette plate-forme.

1) Localisation des fichiers

Chaque document modifiable par un formulaire dans Xdepo est associé à un type de données . Pour un type de données, il peut y avoir plusieurs formulaires. Xdepo connaît les types de données et les formulaires mis à disposition dans une installation en explorant les dossiers et fichiers disponibles à un endroit bien précis.

Prenons comme exemple un type de données dc pour la base de données dont le code est test . S'il y a deux formulaires associés à ce type de données, la structure des fichiers serait la suivante :

01            xdepo-local/datatypes
02                test
03                    dc
04                        forms
05                            forms.xml
06                            form1
07                                binding.xml
08                                default.xml
09                                display.xml
10                                form.xml
11                            form2
12                                binding1.xml
13                                binding2.xml
14                                default.xml
15                                display1.xml
16                                display2.xml
17                                form1.xml
18                                form2.xml

Sur la ligne 5, le fichier forms.xml fournit des informations sur les formulaires disponibles, permettant de leur donner un nom en différentes langues. Ce nom sera affiché dans la liste déroulante du menu de création d'un document.

Ensuite, les dossiers form1 et form2 contiennent tous deux les fichiers de spécification d'un formulaire. Il y a toujours quatre types de fichiers pour un formulaire : binding , default , display et form . Le rôle de ces fichiers est expliqué plus loin dans cette documentation.

Si un formulaire est présenté sur plusieurs pages, on doit répété les fichiers binding , display et form en ajoutant comme suffixe un chiffre (1, 2, ...) qui indique l'ordre des pages. Le formulaire form2 dans l'exemple ci-dessus contient des fichiers de spécification pour un formulaire de deux pages.

2) Le fichier forms.xml

C'est dans ce fichier que vous indiquerez la liste des formulaires disponibles pour un type de données particulier.

Cette liste respecte le format des listes Cforms/Xdepo, comme l'illustre l'exemple ci-dessous :

<fd :selection -list 
    xmlns :fd="http ://apache.org /cocoon/forms/1.0#definition ">
      <fd:item value="form1">
        <fd:label>Mon premier formulaire</fd:label>
    </fd:item>
    <fd:item value="form2">
        <fd:label>Mon second formulaire</fd:label>
    </fd:item>
</fd:selection-list>

A noter que pour les étiquettes, insérées dans l'élément <fd:label> , il est préférable d'utiliser des balises i18n afin de pouvoir les afficher en différentes langues.

3) Le fichier default.xml

Ce fichier contient le modèle par défaut pour les documents édités à l'aide de ce formulaire. Un modèle est un document XML qui contient des valeurs déjà saisies ou au moins la structure de base.

Voici quelques considérations à propos de ce fichier et des modèles de documents en général :

Il est impératif d'ajouter l'attribut xdepo:datatype à l'élément racine de tout modèle, incluant le fichier default.xml . Il doit être de la forme datatypes/[code de base de données]/forms/form[numéro du formulaire] .

Il peut aussi inclure l'attribut xdepo: savetype , pour lequel 3 valeurs sont possibles :

  1. auto : l'identifiant Xdepo du document sera généré automatiquement ;
  2. set : l'identifiant Xdepo du document est entré manuellement lors de la saisie ;
  3. append : l'identifiant Xdepo est le fruit de la concaténation d'un identifiant automatique et d'un identifiant saisi manuellement.

On ne doit pas oublier de déclarer l'espace de nom Xdepo dans ce document :

<test xmlns:xdepo="http://xdepo.org /xdepo/1.0"    
    xdepo:datatype="datatypes/test/forms/form1">
       <identifier>Identifiant par défaut</identifier>
       <title >Titre par défaut</title>
</test>

4) Le fichier form.xml

Dans ce fichier, on y déclare les différents contrôles (widgets ) dans le formulaire. On peut donc considérer que ce fichier contient la définition de base des éléments du formulaire, qui seront réutilisés par ailleurs. Dans la terminologie Cocoon, il s'agit du form definition file .

Pour des informations complètes sur la structure de ce fichier et des contrôles qu'il peut contenir, voir la documentation de Cocoon à ce sujet , et en particulier la partie sur les widgets .

5) Le fichier display.xml

Ce fichier va servir à la mise en page du formulaire, en s'appuyant sur la définition des contrôles dans le fichier form.xml . Dans la terminologie Cocoon, il s'agit du form template .

Vous pouvez mettre le contenu que vous souhaitez dans ce document, puisqu'il ne définit que la mise en page des formulaires. Toutefois, si vous souhaitez rester dans la logique des formulaires Xdepo et de leur intégration dans l'application, voici quelques consignes utiles.

L'élément racine est document . Vient ensuite un élément header , dans lequel on donne le titre de la page et les liens vers les feuilles de style CSS :

<header>
    <title>
        <i18n:text>Test Form</i18n:text>
    </title>
    <style href="lib/xdepo/css/viewer.css"/>
</header>

Ensuite, vous pouvez insérer dans le corps du document un entête qui permettra d'afficher l'identifiant du document en cours de création (s'il existe) :

<body>
    <div class="main">
        <div class="infocontext">
            <p><i18n:text>Test Form</i18n:text> : ${cocoon.request.doc}</p>
        </div>
        ...
    </div>
</body>

Ensuite, vous pouvez insérer le formulaire lui-même, en y mettant sa définition générale. Dans l'environnement Xdepo, il faut lui mettre les informations suivantes :

Voici ce que ça peut donner :

<ft:form-template 
    method="POST" 
    action="#{$continuation/id}.continue?uri=${cocoon.request.uri}&amp;doc=${cocoon.request.doc}" 
    enctype="multipart/form-data">

Vous pouvez ensuite insérer le formatage des erreurs de validation, histoire de les avoir en début de page, comme ceci :

<fi:validation-errors>
     <header>
        <i18n:text key="validation.errors.header"/>
    </header>
     <footer>
        <i18n:text key="validation.errors.footer"/>
     </footer>
</fi:validation-errors>

Le résultat à l'écran sera de la forme suivante :

Pour le formatage du formulaire, utiliser un tableau défini ainsi :

<table align="center" class="general">
    <tbody>
        l'entête
        les éléments du formulaire
        la navigation
    </tbody>
</table>

L'entête du formulaire aura la structure HTML suivante :

<tr>
    <td colspan="2" align="center" class="formHeader">Description</td>
</tr>

A l'écran, vous retrouverez un formatage tel que :

Pour naviguer entre les différentes pages d'un formulaire multi-pages, vous pouvez utiliser trois types de boutons définis ainsi :

  1. précédant : <input type="submit" name="prev" value="Prev" i18n:attr="value"/>
  2. suivant : <input type="submit" name="next" value="Next" i18n:attr="value"/>
  3. sauvegarder : <input type="submit" name="save" value="Save" i18n:attr="value"/>

La structure HTML sera de la sorte :

<tr>
    <td colspan="1" align="left">
        <input type="submit" name="prev" value="Prev" i18n:attr="value"/>
    </td>
    <td colspan="1" align="right">
        <input type="submit" name="save" value="Save" i18n:attr="value"/>
    </td>
</tr>

A l'écran, vous retrouverez un formatage tel que :

Plusieurs contrôles non répétables dans un formulaire seront traités selon ce modèle :

<tr class="groupe">
    <td class="label">
        label de l'élément
    </td>
    <td class="value">
        valeur de l'élément
    </td>
</tr>

Le résultat à l'écran sera semblable à :

L'élément <ft:widget-label> contient l'étiquette associée au formulaire. Toutefois, il ne peut pas être récupéré dans les XSLT de formatage car il est disponible uniquement sous forme de noeud texte. Il faut trouver un moyen de contourner ce problème :

On voudrait pouvoir le traiter pour lui associer la bulle d'aide et l'astérisque des contrôles obligatoires.

L'élément <ft:widget> permet d'afficher le contrôle lui-même. On peut lui rajouter un sous élément <fi:styling> pour surcharger sa mise en forme par défaut. Actuellement, l'astérisque de champ obligatoire, l'aide et l'alerte de validation lui sont associés.

L'élément < fd:field> sans liste définit un contrôle de type zone de texte simple. Avec un sous-élément fi:styling on peut styler, classer, donner un taille à ce contrôle.

<ft:widget id="id1">
    <fi:styling size="40" style="background-color:purple; color:white;"/>
</ft:widget>
<ft:widget id="id2">
    <fi:styling class="forms-field-required"/>
</ft:widget>

Voici des exemples de formatage :

L'élément fi:styling type=" hidden " permet de définir un champ caché.

L'élément fi:styling type=" textarea " permet d'afficher une zone de texte à plusieurs lignes. Par exemple :

<ft:widget id="id3">
    <fi:styling type="textarea" style="background-color:yellow ;"/>
</ft:widget>

Le format d'affichage sera tel que :

L'élément fi:styling type="htmlarea" permet d'afficher une zone de texte riche. Par exemple :

<ft:widget id="id4">
    <fi:styling type="htmlarea" />
</ft:widget>

A l'écran vous obtiendrez un contrôle complexe tel que :

Pour afficher une liste, il existe différentes options. Voici l'affichage par défaut :

Pour une sortie avec des boutons radio, utiliser le formatage fi:styling list-type="radio" ainsi :

<ft:widget id="category6">
    <fi:styling list-type="radio"/>
</ft:widget>

Vous obtiendrez à l'écran quelque chose du genre :

Vous pouvez disposer les mêmes boutons radios à l'horizontal en mod_fiant légèrement l'instruction de mise en forme avec fi:styling list-type="radio" list-orientation="horizontal" , comme dans cet exemple :

<ft:widget id="category6">
    <fi:styling list-type="radio" list-orientation="horizontal"/>
</ft:widget>

Le formatage sera tel que :

Pour obtenir une liste non déroulante mais plutôt à hauteur fixe, utiliser fi:styling list-type="listbox" listbox-size="" , tel que :

<ft:widget id="category2">
    <fi:styling list-type="listbox" listbox-size="10"/>
</ft:widget>

Vous obtiendrez à l'écran :

Si vous optez pour une liste à plusieurs valeurs, utiliser le code fd: multivaluefield et la sortie par défaut sera de la sorte :

Le code fi:styling list-type="listbox" listbox-size="" permet de spécifier la taille de la liste multiple. Attention, dans ce cas précis il n'y aura pas d'ascenseur, donc il ne faut pas donner une taille inférieure au nombre d'items dans la liste.

<ft:widget id="toto">
    <fi:styling list-type="listbox" listbox-size="5"/>
</ft:widget>

Pour présenter les valeurs de la liste dans des cases à cocher, utiliser fi:styling list-type=" checkbox " , comme dans l'exemple suivant :

<ft:widget id="toto">
    <fi:styling list-type="checkbox"/>
</ft:widget>

Le formatage sera tel que :

Pour obtenir une liste double, c'est-à-dire une liste qui permet de sélectionner des items et une autre qui permet de voir les items déjà sélectionnées, utiliser fi:styling list-type="double-listbox" listbox-size="" , comme dans cet exemple :

<ft:widget id="toto2">
    <fi:styling list-type="double-listbox" listbox-size="4"/>
</ft:widget>

Le formatage sera tel que :

Il est souvent intéressant de regrouper des contrôles pour indiquer à l'utilisateur que ces contrôles ont des caractéristiques communes ou qu'ils concernent le même type d'information. Pour ce faire, vous pouvez utiliser une structure HTML telle que celle-ci :

<tr class="groupe">
    <td colspan="2">
        <fi:group>
            <fi:styling type="tabs "/>
            <fi:state >
                <ft:widget id="tab -state "/>
            </fi:state >
            <fi:items>
                <fi:group>
                    <fi:label>Par colonnes</fi:label>
                    <fi:styling layout ="columns "/>
                    <fi:items>
                        <ft:widget id="identifier"/>
                        <ft:widget id="title"/>
                        <ft:widget id="access -control "/>
                    </fi:items>
                </fi:group>
                <fi:group>
                    <fi:label>Par lignes</fi:label>
                    <fi:styling layout ="rows "/>
                    <fi:items>
                        <ft:widget id="size"/>
                        <ft:widget id="accrual "/>
                    </fi:items>
                </fi:group>
                <fi:group>
                    <fi:label>Par colonne</fi:label>
                    <fi:styling layout="column "/>
                    <fi:items>
                        <ft:widget id="standards"/>
                        <ft:widget id="legal-status"/>
                    </fi:items>
                </fi:group>
                <fi:group>
                    <fi:label>Par ligne</fi:label>
                    <fi:styling layout="row "/>
                    <fi:items>
                        <ft:widget id="title2"/>
                        <ft:widget id="title3"/>
                    </fi:items>
                </fi:group>
            </fi:items>
        </fi:group>
    </td>
</tr>

Avec le code fi:styling type=" tabs " , on obtiendra un regroupement par onglets tel qu'illustré ici :

Avec le code fi:styling type=" choice " , le regroupement se fait avec un choix par liste déroulante :

Avec le code fi:styling type="fieldset ", le regroupement se fait dans un fieldset HTML tel que :

Avec un code fi:styling layout="columns" vous obtiendrez une colonne pour les étiquettes et une colonne pour les champs :

Le code fi:styling layout="rows" permet d'obtenir une ligne pour les étiquettes et une ligne pour les champs :

Le code fi:styling layout="column" permet d'obtenir tout sur la même colonne :

Le code fi:styling layout="row" permet d'obtenir tout sur la même ligne :

Certains champs peuvent être répétables. Pour les afficher correctement, incluant les boutons permettant d'ajouter ou supprimer des occurrences, utiliser le code HTML suivant dans le fichier display.xml  :

<tr class="groupe">
    <td colspan="2">
        <fi:group>
            <fi:styling type="fieldset"/>
            <fi:label>
                le label du repeater 
                le bouton add 
            </fi:label>
            <fi:items>
                <ft:repeater-widget id="descriptions">
                    <fi:group>
                        **********quand il y a des sous-éléments*****************
                        <fi:styling type="fieldset"/>
                        <fi:label>
                            le bouton remove
                            le bouton up
                            le bouton down
                        </fi:label>
                        <fi:items>
                            <table align="center">                                                <tbody>
                                    les sous-éléments
                                </tbody>
                            </table>
                        </fi:items>
                        **********sans sous-éléments*****************
                        <fi:label/>
                        <fi:items>
                            le bouton remove
                            le bouton up
                            le bouton down
                            la valeur de l'élément
                        </fi:items>
                    </fi:group>
                </ft:repeater-widget>
            </fi:items>
        </fi:group>
    </td>
</tr>

L'élément ft:repeater-widget-label id="" widget-id="" permet d'afficher l'étiquette du champ répétable, avec les mêmes remarques que pour le code ft:widget-label ci-dessus.

Le bouton d'ajout d'une occurrence peut être inclus ainsi :

<ft:widget id="add{id}">
        <xdepo:button type="img" role="add" code="{id}"/>
</ft:widget>

Le bouton de suppression d'une occurrence peut être inclus ainsi :

<ft:widget id="remove{id}">
        <xdepo:button type="img" role="remove" code="{id}"/>
</ft:widget>

Le bouton permettant de déplacer une occurrence avant la précédente (remonter) peut être inclus ainsi :

<ft:widget id="up{id}">
        <xdepo:button type="img" role="up" code="{id}"/>
</ft:widget>

Le bouton permettant de déplacer une occurrence après la suivante (descendre) peut être inclus ainsi :

<ft:widget id="down{id}">
        <xdepo:button type="img" role="down" code="{id}"/>
</ft:widget>

Ces différents boutons auront la forme suivante :

6) Le fichier binding.xml

Ce fichier contient les instructions qui permettent de lier les éléments du formulaire avec la structure XML du document à modifier ou créer. Ainsi, si vous souhaitez que le contrôle de nom id du formulaire devienne l'élément identifier du document XML, c'est dans le fichier binding.xml que vous devrez le spécifier. Dans la terminologie Cocoon, il s'agit du binding framework .

7) Les balises i18n

Il est possible de générer le contenu textuel des pages des formulaires à l'aide d'instructions I18n de Cocoon, ainsi :

<i18n:text i18n:catalogue="forms" key="test.identifier ">Identifiant par défaut</i18n:text>

Cela signifie que si vous disposez d'un catalogue michael-forms et que ce dernier possède une entrée de type telle que <message key="test.identifier">Mon identifiant</message> alors votre balise i18n sera remplacée par le texte fourni par le catalogue, ici Mon identifiant . Dans le cas contraire la valeur sera le contenu textuel de la balise i18n, soit Identifiant par défaut .

Les catalogues sont référencés dans le fichier xdepo- system/sitemap /sitemap1.xmap ainsi :

<catalogue id="michael-forms" name ="michael-forms" location="xdepo-local/translations"/>

L'attribut id correspond à la valeur de l'attribut i18n:catalogue de la balise i18n:text . L'attribut name renseigne le début du nom du fichier XML correspondant au catalogue, il doit être suivi de _{langue ou locale}. xml .

L'attribut location indique la localisation du catalogue. On a donc ici un catalogue correspondant aux fichiers (pour une application franco-anglaise) :

La forme du catalogue est telle que :

<catalogue xml:lang="{la locale ex: fr}">
    <message key="test.identifier">identifier</message>
    <messages key="...">...</message>
    ...
</catalogue>

De même, dans une balise il est possible de spécifier un attribut i18n:attr={un_nom_d'attribut_de_la_balise un_autre_nom ...} (chaque valeur est séparée par un espace) pour que ces attributs soient traités selon le mécanisme i18n.

La documentation de Cocoon fournit plus d'information sur les mécanismes i18n.