API CFG : #FORMULAIRE_XX

A partir de CFG 1.9, les formulaires dynamiques simplifiés appelés CVT introduits dans SPIP 2.0 (encore en développement) peuvent être utilisés pour sauvegarder des données comme le fait un formulaire classique CFG, avec l’avantage qu’ils deviennent utilisables dans l’interface publique aussi, et ajaxables.

CFG permet de réaliser des formulaires publics, qui s’appuient sur les formulaires dynamiques CVT de SPIP 2.0.

Note : Cette fonction n’est disponible qu’avec une version SPIP 2.0 dev SVN récente. Cette version de SPIP est en développement et n’est pas encore stable. Cette API est donc encore susceptible d’évoluer.

SPIP et les formulaires publics

Une nouvelle API pour réaliser des formulaires publics a été introduit dans la version de SPIP 2.0 en développement. Réaliser un formulaire public nécessite maintenant 2 fichiers :
-  formulaires/x.html contient le formulaire
-  formulaires/x.php contient 3 fonctions :

  • formulaires_x_charger() charge les valeurs par défaut
  • formulaires_x_verifier() vérifie les valeurs envoyées lors de l’envoi du formulaire
  • formulaires_x_traiter() effectue des traitements si les valeurs envoyées sont valides.

Ces formulaires peuvent être rechargés en ajax, c’est à dire que seul la partie contenant le formulaire est actualisée, et non toute la page. Pour utiliser l’ajax, il faut encadrer le formulaire par une classe css ajax, par exemple en l’intégrant dans une balise <div class="ajax">

Fonctionnement des formulaires CVT avec CFG

Lorsqu’un formulaire dynamique placé dans le dossier formulaires/ n’a pas de fonction charger() alors c’est le parseur et les fonctions charger, vérifier et traiter de CFG qui sont utilisées.

Pour appeler un formulaire, il suffit d’indiquer son nom :
-  #FORMULAIRE_X

Il est possible de passer un identifiant (cfg_id) en premier paramètre du formulaire (rarement nécessaire)
-  #FORMULAIRE_X{#ID_ARTICLE}

Adapter le fond CFG

Pour permettre à votre formulaire CFG d’être lu de la sorte, il faut qu’il contienne la balise #ACTION_FORMULAIRE{#SELF} et que le champ action du formulaire soit rempli. Cela donne :

<form method="post" action="#SELF"><div>
#ACTION_FORMULAIRE{#SELF}
...
</div></form>

Attention :
-  [(#ENV{_cfg_}|form_hidden)] n’est plus nécessaire.

Afficher les messages de réussite ou d’echec

l’API des formulaires SPIP retourne plusieurs types de messages qui sont transmis à l’environnement : message_ok, message_erreur ainsi qu’un tableau erreurs qui contient des informations d’erreur pour chaque champ.

Ils s’utilisent comme ceci :

[<p class='formulaire_erreur'>(#ENV*{message_erreur})</p>]
[<p class="formulaire_message">(#ENV*{message_ok})</p>]

[<span class='erreur'>(#ENV**{erreurs}|table_valeur{email_webmaster})</span>]

Formulaire minimal

Soit le formulaire formulaires/z.html contenant :

<!-- titre=Exemple sur le champ 'description' du site -->
<!-- depot=meta -->

#CACHE{0}

[<p class='formulaire_erreur'>(#ENV*{message_erreur})</p>]
[<p class="formulaire_message">(#ENV*{message_ok})</p>]

<form method="post" action="#SELF"><div>
#ACTION_FORMULAIRE{#SELF}

<label>Description du site</label>
<textarea name="description" rows="4" cols="40">[(#ENV{description})]</textarea>
[<span class='erreur'>(#ENV**{erreurs}|table_valeur{description})</span>]

<input type="submit" name="_cfg_ok" value="<:cfg:OK:>" />
</div></form>

Il peut être appelé par #FORMULAIRE_Z.

Le champ description sera enregistré, par défaut, dans z/description (que l’on peut récupérer donc par #CONFIG{z/description}. Pour enregistrer ailleurs, vous pouvez utiliser tous les paramètres CFG à votre disposition. Par exemple en mettant : <!-- nom=ici -->, cela enregistrera la valeur dans ici/description

Intégrer ces formulaires dans les pages ?exec=cfg&cfg=xx

Par défaut, ces formulaires ne s’ajoutent pas aux menus de la page ?exec=cfg, ni ne peuvent être appelés directement avec ?exec=cfg&cfg=xx si le formulaire est nommé #FORMULAIRE_XX.

Pour ajouter ce type de formulaire, il faut créer un autre fond différent du nom du formulaire (donc pas fonds/cfg_xx.html). Ce fond pourra recevoir des paramètres de CFG concernant l’affichage de la page (paramètres onglet, liens). Ce fond devra posséder le paramètre <!-- interpreter=non --> qui indique à CFG qu’il ne doit pas rechercher (analyser la page html retournée) des champs de formulaire dans cette page.

Si ce paramètre n’est pas présent, CFG va considérer les paramètres inclus par les #FORMULAIRE comme des champs à récupérer, ce qui pourrait entrainer des erreurs imprévues (exemple : lire une colonne qui n’existe pas dans une table provoquant une erreur sql).

Pour ces raisons, il est conseillé fortement, dans ce genre de fonds appelant des #FORMULAIRE de ne pas mettre en plus un formulaire CFG classique (<form>...</form>). Par contre, il est tout à fait possible de mettre plusieurs #FORMULAIRE différents.

Exemple de fond/cfg_plugin.html :

<!-- interpreter=non -->
<!-- description=Description de la page -->

<div class='ajax'>
#FORMULAIRE_XX
</div>

<!-- il est possible de mettre plusieurs formulaires dans un même fond -->
<div class="ajax">
#FORMULAIRE_YY
</div>

Discussion

11 discussions

  • Bonjour,

    j’utilise un formulaire CVT comportant un textarea. quand les données
    du formulaire sont erronnées le formulaire doit réafficher
    le contenu du textarea.
    le problème est que le texte est parfois réaffiché en utf-8
    au lieu de l’iso-8859-1, qui est le charset original.

    ceci se produit quand j’active l’ajax. dans ce cas les données
    du POST sont recues en utf-8. j’y accède par un _request().
    celui-ci n’effectue pas toujours la restitution dans le charset original.
    visiblement c’est la constante _AJAX qui n’est plus à 1 dans ce cas.

    la fréquence du problème est assez variable.
    j’ai également observé le problème sur la balise #FORMULAIRE_ECRIRE_AUTEUR
    typiquement avec les champs mail et sujet vides, et en attendant
    plusieurs secondes entre les soumissions successives.

    (je suis en spip 2.07)

    merci pour vos avis

    Répondre à ce message

  • 3
    Philippe

    Bonjour,

    Mon site hébergé chez Strato étant trop lent, j’ai migré chez Infomaniak à Genève avec une IP fixe pour simplifier les tests avant la redirection des DNS. Infomaniak est beaucoup plus rapide. J’ai encore à déboguer le retout à la racine du site...

    Je suis passé de Spip 2.0.8 à Spip 2.0.9 ayant lu l’alerte de sécurité récente.

    • Là, ça se corse : mes formulaires CVT utilisant la balise #SAISIE ne fonctionnent plus (version de cfg : 1.14.0 [30774] et de Spip Bonux : 1.8.1 [30774]).
    • le code source de l’affichage donne :
      <div class="ajax">
      <div class="formulaire_spip">
      <form method="post" action="spip.php?article5"><div>
      <div><input name="article5" value="" type="hidden" />
      <input name="id_article" value="5" type="hidden" />
      <input name="page" value="article" type="hidden" /><input type='hidden' name='formulaire_action' value='selmembres' /><input type='hidden' name='formulaire_action_args' value='FGkk/k3ZMm9PDXhhjF2nqH2XfwmtwTPEqcWMzTn9trs9Q4ImhXbuMZktrc1kCb2xx7GGKI2B6sVpL63Dbg0rfVPd' /></div>
      <ul>
      		{checkbox,categ}	
      		{checkbox,sexe}
      		{checkbox,licence}
      		{radio,tri}
      </ul>
      <p class="boutons">
          <input class="submit" type="submit" name="valider" value="Valider" />
      
      </p>
      </div></form>

    Je n’ai rien changé aux formulaires eux mêmes. Que peut-il se passer ?

    Voir le problème sur le site d’Annemasse Ski Compétition

    Merci

    Philippe

    • marcimat

      Saisies a évolué (je rappelle qu’il a le statut expérimental) : tu dois mettre à jour CFG et Saisies ET repprendre ton formulaire HTML en t’appuyant sur les exemples de saisies donné dans le répertoire saisies du plugin homonyme :

      [(#SAISIE{type, champ}{option=x}{option=y})]
      devient :
      [(#SAISIE{type, champ, option=x, option=y})]
    • Philippe

      Bonjour Matthieu,

      Durant ma migration chez Infomaniak, j’ai installé cfg comme plugin auto or le répertoire « saisie » est absent du paquet auto installable.

      C’est normal pusque la balise #SAISIE est encore expérimentale. La copie du répertoire "saisie" ancienne versionne semble pas marcher non plus. Je vais chercher s’il existe un zip contenant tout ou mieux pourrais-tu me le faire passer ?

      -  Dans SPIP ZONE, tu écris

      Migration des anciennes saisies
      --------------------------------
      
      1) Mettre à jour CFG en version 0.13 minimum
      2) ajouter et activer le plugin "saisies"
      3) modifier vos squelettes SPIP :

      Je ne trouve nulle part de plugin « saisie ». En existe-t-il un ou s’agit-il du déplacement du répertoire « saisie » ?

      Merci

      Philippe

    • marcimat

      Saisie est devenu un plugin à part, tu peux le récupérer là :
      http://files.spip.org/spip-zone/saisies.zip

    Répondre à ce message

  • 1

    Bonjour Matthieu,

    Merci pour cette solution qui marche à merveille.

    J’ai plusieurs observations :
    -  Il ne faut pas “ajaxer” le formulaire faute de quoi, les champs ne sont pas remplis au deuxième passage. J’ai placé :
    [(#ENV*{numero}>{0}|oui)<div class="ajax">]   à la première ligne de mon formulaire pour ajaxer le formulaire uniquement en cas de modification.
    — N.B. mon formulaire HTML NE CONTIENT PAS DE CHAMP NOMME “nouvel_id”
    — $numero restera toujours égal à zéro après un _request(’numero’).
    — J’arrive sur la page du formulaire avec le paramètre &numero=x. x=0 en cas de création ou x = Id de l’enregistrement à modifier.

    -  concrètement, j’ai utilisé la méthode suivante :
    — Fonction Charger :

    $numero=_request('numero');    à zéro en cas de création. “nouvel_id” n'existe pas au premier passage.
    if (_request('nouvel_id')) {            
        $numero=_request('nouvel_id');   contient par la suite l'Id de l'enregistrement en cours. 
        settype($numero, "integer");
    }
    if ($numero>0) {
            .../...
            $query = "SELECT * FROM adherents WHERE numero=$numero;" ;
            .../...
     	while ($row = mysql_fetch_array($resultat, MYSQL_BOTH)) {
    		$nom= $row["nom"]; 
           .../...
        									 
           $valeurs = array('numero'=>$numero, 'nom'=>$nom, .../...)   initialisation du formulaire avec les données de la table
    }else{
           if (_request('nouvel_id')) {
    	   die("je ne devrais jamais passer ici !"); 
           }
           $valeurs = array('numero'=>'0', 'nom'=>'', .../...)   initialisation du formulaire vide
    }
    return $valeurs;


    — Fonction Vérifier : RAS
    — Fonction Traiter :

    		$numero=_request('numero');
    		if (_request('nouvel_id')) {
    			$numero=_request('nouvel_id');
    			settype($numero, "integer"); 
    		}
    		$nom = _request('nom');
                    .../...
    		if ($numero>0){ 
                           $query = "UPDATE ....
    		}else{
                           $query = "INSERT ...
                           $numero=mysql_insert_id();
    		}
    		set_request('nouvel_id',$numero);
    		return array('message_ok'=>$message);

    Le set_request va créer un nouveau champ caché sur la page HTML ayant comme valeur l’Id de l’enregistrement nouvellement créé ou celui de l’enregistrement en cours.

    Pour une création dans la table, mon code va donc faire les choses dans l’ordre suivant :

    -  1er passage : affichage d’un formulaire vide ($numero=0)
    -  après validation : création de l’enregistrement dans la table, récupération de l’Id auto incrémenté puis ré affichage du formulaire avec passage dans la fonction Charger. L’Id étant renseigné (“nouvel_id”), l’enregistrement nouvellement créé est relu comme si j’arrivais sur la page du formulaire avec &numero > 0.
    -  apres RE VALIDATION : MODIFICATION de l’enregistrement puis ré affichage
    -  ainsi de suite pour autant de modifications qu’on veut.

    Je vais creuser un peu autour du fait de ne pas pouvoir ajaxer le formulaire. J’ai peut-être fait une erreur quelque part.

    Code source de la page HTML au 2e passage :

     
    .../...
    <form method='post' action='spip.php?article46&amp;id_article=46'>
    	<div>
    		<div><input name="article46" value="" type="hidden" />
    <input name="id_article" value="46" type="hidden" />
    <input name="nouvel_id" value="472" type="hidden" />   champ créé par la fonction set_request() dans la fonction Traiter
    .../...

    Si ça peut aider ...

    Philippe

    • Un petit « UP » concernant Ajax.

      Je me suis mal exprimé dans le Post précédent.

      Si on « ajaxe » le formulaire, les valeurs sont bien affichées à l’écran lors du deuxième passage MAIS dans le code source de la page la « VALUE » des champs est à «  ». Dans mon cas précis, le champ nouvel_id créé par la fonction set_request() ne garde alors pas la valeur assignée et donc la méthode ne donne pas le résultat escompté.

      En ajaxant, chaque validation entraîne une nouvelle création dans la table avec un nouvel Id et non pas une modification de l’enregistrement qui vient d’être créé.

      Philippe

    Répondre à ce message

  • 1
    Philippe Guérindon

    Bonjour,
    Je reviens chercher de l’aide sur ce Forum.

    Je ne maîtrise pas encore bien toutes les finesses des formulaires CVT et ma question est la suivante :

    -  Existe-t-il une méthode pour modifier les variables d’environnement dans la fonction “Traiter” d’un formulaire ?

    J’ai un formulaire qui fait les choses suivantes :

    1. à partir d’une liste, je récupère la clef primaire auto incrémentée d’un enregistrement puis je chaine sur la page du formulaire
    2. la fonction “Charger” ouvre la base de données, et récupère les données.
    3. les fonctions “Vérifier” et “Traiter” font les contrôles et l’UPDATE de la base (utilisé par les membres pour modifier leur fiche).

    Tout fonctionne parfaitement dans ce cas de figure.

    Je me sert du même formulaire pour ajouter un enregistrement dans la base (utilisé par les administrateurs pour créer une fiche).

    1. Je chaine sur la page avec un Id à zéro
    2. l’Id à zéro m’indique que je dois initialiser le formulaire à blanc
    3. les fonctions “Vérifier” et “Traiter” font les contrôles et l’INSERT dans la base.

    L’idée est de récupérer la valeur du dernier auto incrément par mysql_insert_id () par exemple, ET DE MODIFIER la valeur de #ENV{numero} qui deviendrait disponible lors du ré affichage de mon formulaire après validation.
    Le ré affichage du formulaire se ferait comme si j’arrivais sur la page en chainant l’ID nouvellement créé. Cela me permettrais d’appliquer des filtres sur les balises pour obtenir tel ou tel affichage particulier (chemin vers une photo en combinant le nom et le prénom notamment).

    Pour le moment, une re validation du formulaire me refait un INSERT étant donné que ma variable d’environnement reste à zéro. Je n’arrive pas à changer quoi que ce soit dans le formulaire comme placer la valeur de l’ID dans un champ caché du formulaire ou dans autre chose. Je n’ai pas encore essayé par la création d’une variable de SESSION mais j’attends une piste avant de me fourvoyer.

    J’aurais bien une solution mais elle est très lourde :

    1. Ouvrir une transaction
    2. faire l’INSERT dans la fonction Vérifier,récupérer la valeur de l’auto incrément puis générer une erreur pour revenir au formulaire.
    3. Obliger l’utilisateur (moi) à valider à nouveau le formulaire et faire un UPDATE pour rien puis valider la transaction.
    4. ou annuler la transaction par un moyen à trouver en cas de sortie sans revalidation.

    Une autre solution consisterait à détourner la fonction Vérifier de son objet principal et de tout faire dans celle-ci sans jamais passer par la fonction Traiter.

    Dans la mesure où seuls les administrateurs du site font les créations d’enregistrements, ça doit être jouable. Les membres qui modifient leur propre fiche le font par la voie normale sans souci.

    Pour gagner du temps, j’ai créé mon formulaire en mixant les INPUT, SELECT et autres avec des boutons radio et des checkbox de la balise SAISIE. Je ferai tout migrer sur la balise SAISIE au fur et à mesure de la maîtrise que j’en aurai.

    Merci pour une idée.

    Philippe

    • marcimat

      Bonjour Phillipe,

      Peut être que cette solution peut te convenir (expliquée vaguement ici : http://marcimat.magraine.net/Creer-une-interface-d dans le paragraphe « Effectuer un traitement par le formulaire CVT ») :

      • dans le traitement, sauver le nouvel id par set_request('nouvel_id',$id_machin);
      • dans le charger, tester sa présence et agir en conséquence : if ($id_machin = _request('nouvel_id')) { .... }

      MM.

    Répondre à ce message

  • Philippe Guérindon

    Bonjour,

    La cause de mes soucis d’alignement venait du css de mon squelette qui prend la main sur celui de “Spip-Bonux”.
    -  j’avais beau modifier tout ce que je voulais dans le fichier “style_prive_formulaires.html”, rien ne changeait. J’ai donc modifié le fichier “base.css” de Sarka-Spip en incluant la bonne ligne.
    -  le message d’erreur persiste après l’effacement du cache mais on ne va pas y passer 1 seconde car tout rentre dans l’ordre au 2e affichage de l’article par la remise en cache des pages html du plugin au premier passage.
    -  l’initialisation du formulaire en passant un “array” à la balise #SAISIE marche normalement. J’ai été assez mauvais sur ce coup là !
    -  pour le tri sur plusieurs champs de la base, je vais me pencher sur la fonction que tu indiques. Là encore on ne va pas y passer trop de temps.

    Merci beaucoup pour le support.

    Philippe

    P.S. les fichiers de mon formulaire (à adapter à votre sauce et à renommer, si j’ai le droit de placer les liens ici ?)
    -  N.B. C’est la balise #SAISIE qui place les “<li>” et “</li>” dans le formulaire.

    télécharger : le formulaire html et
    le fichier php des fonctions CVT

    Répondre à ce message

  • 1
    Philippe Guérindon

    Bonjour Marcimat,

    Merci pour cette balise SAISIE. Tout est devenu beaucoup plus simple tout d’un coup.

    J’ai plusieurs observations :
    -  étant donné que l’on est plus dans un contexte <ul> <li>, j’ai du mal à personnaliser l’affichage des items des balises SAISIE. Le code de la boucle POUR de spip Bonux les affichant :

    <BOUCLE_radio(POUR){tableau #ENV{datas}}>
    <div class="choix">
       <input type="checkbox" name="#ENV{nom}[]" class="checkbox"
          id='champ_#ENV{nom}_#COMPTEUR_BOUCLE'
          [(#CLE|in_any{[(#ENV{valeur}|sinon{#GET{defaut}})]}|oui)checked='checked']
          value='#CLE' />
        <label for="champ_#ENV{nom}_#COMPTEUR_BOUCLE">#VALEUR</label>
    </div>
    </BOUCLE_radio>

    permet-il l’affichage sur une même ligne (du style .choix display:inline ;) ? Peut être par un style float ?
    -  Le vidage du cache (ou le recalcul de la page) génère chez-moi une erreur de squelette dans la construction de la boucle lors du premier affichage du formulaire suivant le vidage. Pour mon exemple (voir les posts plus bas), le critère “categ” est inconnu dans la requête SQL générée. Je ne comprends pas pourquoi. C’est comme si Spip évaluait ma boucle avant le chargement des pages cfg/saisies du plugin. Je précise que tous mes tests se font « en grandeur » sur le site hébergé.. Par la suite il doit les trouver dans le cache.

    message d’erreur :

    Erreur(s) dans le squelette
    
    1  	Erreur sur le site 	boucle critère inconnu categ


    -  Dans la balise SAISIE qui sert pour faire mon tri,

    [(#SAISIE{radio,tri}
            {label=Tri}
            {defaut=nom}
            {datas=#ARRAY{
               nom,Par nom,
               annee,Par âge,}})]

    , serait-il possible de permettre une chaine de caractère au lieu d’un mot unique. L’idée serait de remplacer dans l’exemple ci-dessus, « nom » par « nom prenom » de façon à pouvoir trier sur plusieurs critères.
    -  Je n’arrive toujours pas à initialiser le formulaire avec des critères par défaut. Comment faudrait-il faire pour que ma boucle affiche le formulaire en arrivant sur la page comme si toutes les cases étaient cochées ? Les lignes default=xxx des balises saisie ne changent rien. Ici encore ma boucle doit être interprétée avant le chargement et le traitement des balises SAISIE.
    — ma fonction charger :

    function formulaires_selmembres_charger_dist(){
    	$valeurs = array('categ'=>'microbe,poussin,benjamin,minime,cadet,junior,tous', 'sexe'=>'H,L', 'licence'=>'2,1', 'tri'=>'nom'); 
    	return $valeurs;
    }

    Le code de ma boucle suivant le </form> est devenu plus simple :

    <BOUCLE_adherents(adherents categories) {categ IN #ENV**{categ}}{sexe IN #ENV**{sexe}}{licence IN #ENV**{licence}} {par #ENV**{tri}}{inverse #GET{senstri}}>
    	<tr class="[(#COMPTEUR_BOUCLE|alterner{'row_even','row_odd'})]">
    		<td>#NOM</td>	
    		.../...>
    	</tr> 
    </BOUCLE_adherents>

    Encore merci pour le plugin.
    Philippe

    P.S. Pour ceux qui voudraient voir le formulaire en action, le numéro de mon article à changé à la suite d’une réinstallation totale de Spip (plantage massif avec la dernière version svn à cause de l’absence de définition de certains filtres d’images et donc incompatibilité avec mon squelette). Je n’ai pas pu m’en sortir autrement que par un vidage de la base et effacement des répertoires. La version Spip 2 (2.0.8 à la date du post) de mon site tourne dans le sous-domaine spip.asc-annemasse.com et le lien pour y aller est ICI. L’article « Liste des membres » se trouve dans la rubrique "Qui sommes-nous".

    • marcimat

      Philippe,

      Pour l’affichage en liste / en ligne, dans le CSS de SPIP Bonux est indiqué :

      /*
      *  La liste par defaut est verticale
      *  pour l'avoir horizontale, il faut specifier :
      *  .formulaire_spip .formulaire_editer .editer_qqc .champ{display:inline;}
      */

      Dans ton cas, ça peut être, je suppose :

      .formulaire_spip .editer_categ .choix {display:inline;}


      Erreur(s) dans le squelette
      1 Erreur sur le site boucle critère inconnu categ

      Aucune idée, ta boucle a l’air correcte pourtant...


      Pour la saisie « par nom, prenom » je vois pas trop comment faire (et j’ai pas trop envie là de réfléchir !)... Faut certainement dans la fonction charger analyser _request(’tri’) et faire des choses en conséquance pour remplir correctement $valeurs.


      Pour les chargements par défaut : 2 possibilités :

      1) la fonction charger (mais c’est un array qu’il faut, pas une liste à virgule pour la boucle POUR) :

      function formulaires_selmembres_charger_dist(){
              $valeurs = array('categ'=>array('microbe','poussin','benjamin','minime','cadet','junior','tous'), 'sexe'=>array('H','L'), 'licence'=>array('2','1'), 'tri'=>'nom');
              return $valeurs;
      }

      2) le parametre defaut, et IDEM, si tu as plus d’un élément, c’est un array qu’il faut :

      {defaut=#ARRAY{0,microbe,1,poussin,2,bajamin}}

      Bon courage.

    Répondre à ce message

  • 1
    Philippe Guérindon

    Merci Marcimat (Matthieu) pour ces explications,

    J’ai à peu près fait le tour de la question et je n’ai pas trouvé de solution aux trois choses suivantes :
    -  initialiser le formulaire, quoique je mette dans la « fonction charger »
    -  conserver les valeurs des cases à cocher lors du ré affichage du formulaire
    -  récupérer et utiliser directement la valeur de la case à cocher pour l’ordre de tri. Je suis passé par une boucle condition de spip-bonux (encore merci).

    L’ajaxisation du formulaire est par ailleurs obligatoire sous peine d’avoir un vilain message d’avertissement causé par les tableaux d’input.
    -  Je place ci-dessous mes codes qui pourront donner des idées à ceux qui pataugent.

    le résultat est visible sur mon site en migration (suivez ce lien).

    Encore merci.

    Philippe

    mon formulaire :

    <div class="ajax">
    <div class="formulaire_spip formulaire_selmembres">
    	[<p class='formulaire_erreur'>(#ENV*{message_erreur})</p>]	
    	<form action='#ENV{action}' method='post'>
    		#ACTION_FORMULAIRE{#ENV{action}}
    	<hr> 
    	<table class="spip">
    	<thead>
    		<tr class='row_first'>
    			<th scope="col" colspan="4" style="text-align: center"><strong class="spip">Filtrage des membres</strong></th>
    		</tr>
    	<tbody>	
    		<tr class="row_even">
    			<td > <input type="checkbox" name=categ[] value="microbe" class="checkbox" / > Microbes</td> 
    			<td> <input type="checkbox" name=categ[] value="poussin" class="checkbox" /> Poussins</td> 
    			... 
    		</tr> 
    		<tr class="row_even">
    			<td> <input type="checkbox" name=categ[] value="cadet"  class="checkbox" / > Cadets</td> 
    			<td> <input type="checkbox" name=categ[] value="junior"  class="checkbox"  /> Juniors</td> 
    			...
    		</tr> 
    		<tr>
    			<td colspan="4"><hr></td>
    		</tr>
    		<tr class="row_even">
    			<td> <input type="checkbox" name=sexe[] value="H"  class="checkbox"  /> Garçons	</td> 
    			<td> <input type="checkbox" name=sexe[] value="L"  class="checkbox"  /> Filles </td> 
    			<td> <input type="checkbox" name=licence[] value="2"  class="checkbox"  /> Licences	</td> 
    			<td> <input type="checkbox" name=licence[] value="1"  class="checkbox"  /> C.Neige </td> 
    		</tr> 
    		<tr class="row_even">
    			<td colspan="2"> <input type="radio" name=tri[] value="0"  class="radio"  checked /> Tri par Noms</td> 
    			<td colspan="2"> <input type="radio" name=tri[] value="1"  class="radio" /> Tri par Age</td> 
    		</tr> 
    		<tr class="row_even" >
    			<td class="boutons" colspan="4"><center><input class="submit" type="submit" name="valider" value="Valider" /></center>	</td>
    		</tr> 
    	</tbody>	  
    </table>
    </form>
    
    <table class="spip" width="100%"><thead>
    <tr class="row_first" style="text-align: center"><th scope='col'><strong class="spip">Nom</strong></th><th scope='col'><strong class="spip">Pr&eacute;nom</strong></th><th scope='col'><strong class="spip">Ann&eacute;e</strong></th><th scope='col'><strong class="spip">Categ.</strong></th><th scope='col'><strong class="spip">Titre FFS</strong></th><th scope='col'><strong class="spip">Sexe</strong></th></tr>
    [(#SESSION{statut}=={'0minirezo'}|ou {#SESSION{statut}=={'6forum'}}) <tr class='row_first'><th scope='col'><strong class="spip">Rue</strong></th><th scope='col'><strong class="spip">Suite</strong></th><th scope='col'><strong class="spip">C.postal</strong></th><th scope='col'><strong class="spip">Ville</strong></th><th scope='col'><strong class="spip">Portable</strong></th><th scope='col'><strong class="spip">Tel.</strong></th></tr>]	
    
    <tbody>
    <BOUCLE_triee(POUR){tableau #ENV*{tri}}> 
    	<BOUCLE_test12(CONDITION){si #VALEUR|={0}}>
    		<BOUCLE_adherents1(adherents categories) {categ IN #ENV*{categ}}{sexe IN #ENV*{sexe}}{licence IN #ENV*{licence}} {par annee}{inverse}{par nom, prenom}{"----"}>
    		    <tr class="[(#COMPTEUR_BOUCLE|alterner{'row_even','row_odd'})]">
    				[(#SESSION{statut}=={'0minirezo'}|ou {#SESSION{statut}=={'6forum'}}) <td><a href="http://www.asc-annemasse.com/spip/spip.php?article24&numero=#NUMERO&var_mode=recalcul">#NOM</a></td> ]	
    		    	[(#SESSION{statut}|strlen|=={0}|oui) <td>#NOM</td>]
    				<td>[(#PRENOM|chainespg::car1majuscule)]</td><td>#ANNEE</td><td>#CATEGLIB</td><td>[(#NUMERO_LICENCE|chainespg::lienlicence{#NOM, #PRENOM})] [(#NUMERO_CARTENEIGE|chainespg::lienlicence{#NOM, #PRENOM})]</td><td>[(#SEXE|=={H}|oui)Homme][(#SEXE|=={H}|non)Dame]</td>
    			</tr> 
    			[(#SESSION{statut}=={'0minirezo'}|ou {#SESSION{statut}=={'6forum'}}) 
    			<tr class="[(#COMPTEUR_BOUCLE|alterner{'row_even','row_odd'})]">
    				<td>#ADRESSE1</td><td>#ADRESSE2</td><td>#CODE_POSTAL</td><td>#VILLE</td><td>#PORTABLE</td><td>#TELEPHONE1</td>
    			</tr>]	
    		</BOUCLE_adherents1>  
    	</BOUCLE_test12>
    		<BOUCLE_adherents2(adherents categories) {categ IN #ENV*{categ}}{sexe IN #ENV*{sexe}}{licence IN #ENV*{licence}} {par nom, prenom}>
    		    <tr class="[(#COMPTEUR_BOUCLE|alterner{'row_even','row_odd'})]">
    				[(#SESSION{statut}=={'0minirezo'}|ou {#SESSION{statut}=={'6forum'}}) <td><a href="http://www.asc-annemasse.com/spip/spip.php?article24&numero=#NUMERO&var_mode=recalcul">#NOM</a></td> ]	
    		    	[(#SESSION{statut}|strlen|=={0}|oui) <td>#NOM</td>]
    				<td>[(#PRENOM|chainespg::car1majuscule)]</td><td>#ANNEE</td><td>#CATEGLIB</td><td>[(#NUMERO_LICENCE|chainespg::lienlicence{#NOM, #PRENOM})] [(#NUMERO_CARTENEIGE|chainespg::lienlicence{#NOM, #PRENOM})]</td><td>[(#SEXE|=={H}|oui)Homme][(#SEXE|=={H}|non)Dame]</td>
    			</tr> 
    			[(#SESSION{statut}=={'0minirezo'}|ou {#SESSION{statut}=={'6forum'}}) 
    			<tr class="[(#COMPTEUR_BOUCLE|alterner{'row_even','row_odd'})]">
    				<td>#ADRESSE1</td><td>#ADRESSE2</td><td>#CODE_POSTAL</td><td>#VILLE</td><td>#PORTABLE</td><td>#TELEPHONE1</td>
    			</tr>]	
    		</BOUCLE_adherents2>  
    	<//B_test12>
    </BOUCLE_triee>
    
    </tbody>								  
    </table>	
    </div>		 
    </div>		 

    mon fichier de fonctions :

    <?php
    
    function formulaires_selmembres_charger_dist(){
    	$valeurs = array('categ'=>'', 'sexe'=>'', 'licence'=>'', 'tri'=>''); 
    	return $valeurs;
    }
    
    function formulaires_selmembres_verifier_dist(){ 
    	$erreurs = array();
    	$erreurs['message_erreur']= ' ';
    	return $erreurs;
    }						   
    
    function formulaires_selmembres_traiter_dist(){	 
    	$erreurs = array();
    	return $erreurs;
    }
    ?>
    • marcimat

      Bonjour Philippe,

      Quelques points qui pourront t’aider :

      • Préférer une écriture standard de SPIP 2 pour les formulaires que tu écris (voir http://programmer.spip.org/-Les-formulaires), notamment un enchainement UL/LI avec éventuellement des fieldset.
      • Pour le tri tu peux utiliser {par #ENV{mon_tri} #GET{sens}} en calculant le sens en fonction de mon_tri : [(#SET{sens,[(#ENV{mon_tri}|=={nom}|?{0,1})]})]

      Si tu utilises une écriture de formulaires comme le prévoit SPIP 2.0, tu peux essayer la balise #SAISIE de CFG (non documentée car encore en test). Notamment la saisie « checkbox » (nécessite aussi SPIP Bonux) que je viens juste de t’ajouter (version CFG 1.12.5) (http://zone.spip.org/trac/spip-zone/changeset/28852), que tu peux utiliser de la sorte :

      <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>]
      
      
      <form method="post" action="#ENV{action}"><div>
      #ACTION_FORMULAIRE{#ENV{action}}
      
      <h3 class="legend">Filtrage des membres</h3>
      <ul>
      
      [(#SAISIE{checkbox,categ}
          {label=Catégorie}
          {datas=#ARRAY{
              microbes,Microbes,
              poussin,Poussin,
              cadet,Cadet,
              junior,Junior,
      }})]
      
      [(#SAISIE{checkbox,sexe}
          {label=Sexe}
          {datas=#ARRAY{
              H,Garçon,
              F,Fille,
      }})]
      
      [(#SAISIE{checkbox,licence}
          {label=Sexe}
          {datas=#ARRAY{
              2,Licences,
              1,C. Neige,
      }})]
      
      [(#SAISIE{radio,tri}
          {label=Tri}
          {defaut=nom}
          {datas=#ARRAY{
              nom,Par nom,
              annee,Par âge,
      }})]
      </ul>
      
      <p class="boutons">
          <input class="submit" type="submit" name="valider" value="Valider" />
      </p>
      
      </div></form>
      
      ... ta boucle ...
      
       </div>

      Enfin, attention dans ton code à bien fermer des <input> car certains ont : <input ... / > avec un espace entre / et > ...

      Dernière chose : le plugin Bonux a aussi un critère tri exprès pour trier... mais je n’ai pas joué avec encore...

    Répondre à ce message

  • 1
    Philippe Guérindon

    Bonjour,
    -  Je ne poste certainement pas au bon endroit mais je cherche de l’aide partout, je tourne en rond depuis plusieurs semaines sans trouver de solutions.
    -  Je souhaite faire un formulaire CVT pour construire une requête sur une table externe (membres du club).

    J’ai essayé la méthode suivante :
    -  je place <article|xxx> dans un article : cela appelle le modèle correspondant.
    -  dans le modèle en question, je place la ligne : #FORMULAIRE_SELMEMBRES qui appelle mon formulaire.

    mon formulaire est conforme au tutorial des formulaires CVT par l’exemple (avec les 3 fonctions dans selmembres.php).

    L’idée est la suivante :
    -  Récupérer les données (cases à cocher) du formulaire. Je sais le faire jusqu’à la fonction « formulaires_selmembres_traiter_dist() ».
    -  Je sais faire un traitement à l’intérieur de la fonction mais je ne sais pas revenir à l’affichage de la page en récupérant le résultat du traitement de la fonction pour afficher les enregistrements filtrés de la base. Le seul moyen que j’ai trouvé pour récupérer le résultat de la fonction consiste à le mettre dans « message_ok ».

    Je ne vois pas la solution.

    En résumé : article -> modèle -> formulaire -> traitement dans la fonction « formulaires_selmembres_traiter_dist() ». -> retour au modèle -> affichage des enregistrements filtrés soit par php ou mieux par une boucle.

    J’imagine que la puissance de la modélisation associée au formulaire CVT doivent être capable de faire cela.

    Merci pour le support.
    Philippe

    P.S. sous Spip 1.9 et tout en php : http://www.asc-annemasse.com/spip/spip.php?article15 (opérationnel)

    en migration sous Spip 2 avec formulaire CVT : http://spip.asc-annemasse.com/spip.php?article16 (je galère)

    • marcimat

      Pour ton cas, ça ne me semble pas si difficile que cela... en plus, tu n’as pas besoin de traitement en base de donnée, juste de faire une sélection sur ta boucle qui affiche ton tableau...

      En gros : tu as article 15 qui appelle <formulaire|xx> ou même si tu le souhaites <div class="ajax"><formulaire|xx></div>.

      Ce formulaire serait dans le fichier : formulaires/xx.html et formulaires/xx.php. La fonction charger retournerait l"environnement attendu (variables « sexe » et « categorie » par exemple). La fonction verifier() renverrait toujours une erreur ($erreurs[’message_erreur’] = «  » ; pour faire réafficher systématiquement le formulaire - puisqu’il n’y a aucun traitement à effectuer, juste une sélection).

      Les checkbox auraient des name=« yy[] », « zz[] » où yy est le nom du champ de la table SQL... Ensuite, c’est un petit tour de passe passe dans le html du formulaire :

      <div class="formulaire_spip">
      <form...><div>#ACTION_FORMULAIRE{#ENV{action}}
      ... les checkbox ...
      </div></form>
      
      ... ici la boucle ...
      <BOUCLE_selection_ski(SKIEURS){yy IN #ENV{yy}}{zz IN #ENV{zz}} {!par date}>
      
      </BOUCLE>
      
      </div>

      Tout consiste ensuite à passer au formulaire une syntaxe correcte au #ENVyy en absence de checkbox cochée : il suffit de définir les valeurs par défaut dans le charger à « .* » et ça devrait rouler...

    Répondre à ce message

  • marabbeh

    J’ai malheureusement le même problème que toi, Philippe. Et j’aimerais de plus modifier une ou des tables externes (DELETE, UPDATE, INSERT). Pourtant les fonctions spip existent, mais comment les utiliser ? Je ne sais pas. Je cherche de la doc moi aussi...

    Répondre à ce message

  • Mise à jour de la documentation le 16 juillet :
    -  #FORMULAIRE_CFG{x} disparait au profit de #FORMULAIRE_X directement (cfg 1.9 / spip 2.0 dev svn)

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom