Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 24-01-2011 11:55:14

CinePhil
Membre
Date d'inscription: 24-03-2010
Messages: 19

[ZF 1.11] Dojo : Changer formulaire sur action de l'utilisateur

Bonjour,

1) Le contexte
Soit un formulaire qui affiche les données existantes d'un étudiant et que celui-ci peut compléter et/ou modifier.
Si l'établissement d'origine de l'étudiant est déjà enregistré en BDD, le formulaire affiche simplement le nom de l'établissement et son adresse.
Si cet établissement n'est pas encore connu, le formulaire affiche une Zend_Dojo_Form_Element_ComboBox contenant la liste des établissements déjà connus en BDD et, puisque c'est une Combobox, l'étudiant a la possibilité de taper le nom d'un nouvel établissement, ainsi que son adresse et son téléphone, afin que celui-ci soit ajouté en BDD.

2) Le besoin
Je voudrais faire en sorte que lorsque l'étudiant choisit un établissement dans la combobox, les coordonnées de celui-ci apparaissent à la place des zones de saisie.

3) Où j'en suis
Extrait de la vue infosperso.phtml :

Code:

    <h2>Votre établissement d'origine</h2>
    <?php if($this->form->etb_id->getValue() == '') : ?>
        <!-- Établissement de l'étudiant non encore connu => Formulaire de saisie  -->
        <?php echo $this->form->etb_id; 
        //echo $this->form->etb_nom;
        echo $this->form->etb_adresse;
        echo $this->form->etb_code_postal;
        echo $this->form->id_commune_etablissement;
        echo $this->form->etb_telephone;
        echo $this->form->te_id;
        ?>
    <?php else :?>
        <!-- Établissement déjà en BDD => Affichage des coordonnées  -->
        <dl>
            <dt>Nom</dt>
            <dd><?php echo $this->escape($this->infos_etudiant['etb_nom']); ?></dd>
            <dt>Adresse</dt>
            <dd>
                <?php echo $this->escape($this->infos_etudiant['etb_adresse']); ?><br />
                <?php echo $this->escape($this->infos_etudiant['etb_code_postal']); ?> 
                <?php echo $this->escape($this->infos_etudiant['nom_commune_etablissement']); ?>
            </dd>
        </dl>
    <?php endif; ?>

Extrait du formulaire infosperso.php :

Code:

        // Établissement d'origine de l'étudiant
        // Liste de choix
        $etb_id = new Zend_Dojo_Form_Element_ComboBox('etb_id');
        $etb_id
            ->setLabel('Nom')
            ->setAutoComplete(false)
            ->setStoreId('etbStore')
            /*->setStoreType('dojo.data.ItemFileReadStore')*/
            ->setStoreType('custom.CustomQueryReadStore')
            ->setStoreParams(array(    'url' => '/stagmas/public/accueiletudiant/listeetb',
                                    'requestMethode' => 'get'))
            ->setAttrib('searchAttr', 'etb_nom')
            ->setAttrib('onChange', "coordetb(dijit.byId('etb_id').attr('value'))")
            ->setRequired(false);

=> Avec le dojo.data.ItemFileReadStore, j'affiche bien la liste des établissements connus en BDD.

Extrait du controleur Accueiletudiant.php :

Code:

    public function listeetbAction()
    {
        $db = Zend_Db_Table_Abstract::getDefaultAdapter();
        $listeetb = $db->fetchAll("
            SELECT etb_id, etb_nom 
            FROM te_etablissement_etb
        " );
        //$tabcommunes = $listecommunes->toArray();
        $data = new Zend_Dojo_Data('etb_id', $listeetb);
        $this->_helper->autoCompleteDojo($data);
    }
        
    /**
     * Construit la donnée Dojo contenant l'établissement d'origine de l'étudiant
     * 
     */
    public function getEtablissementOrigineAction()
    {
        $etbnom = $this->_request->getParam('etb_id');
        $etablissement = new Application_Model_DbTable_Etablisssment();
        $result = $etablissement->getEtablissementParNom($etbnom);
        $data = new Zend_Dojo_Data('etb_id', $result);
        $this->_helper->autoCompleteDojo($data);
    } // Fin public function getEtablissementOrigine($idetb)

Extrait du modèle Etablissement.php :

Code:

    /**
     * Retourne les coordonnées complètes d'un établissement
     * @param int $id
     */
    public function getEtablissementParNom($nom)
    {
        $sql = "
            SELECT e.etb_id, e.etb_nom, e.etb_adresse, e.etb_code_postal, e.etb_telephone, 
                c.cmn_nom,
                te.te_libelle 
            FROM te_etablissement_etb e 
            INNER JOIN tr_commune_cmn c ON c.cmn_id = e.etb_id_commune 
            INNER JOIN tr_type_etablissement_te te ON te.te_id = e.etb_id_type_etablissement 
            WHERE e.etb_nom = :nom 
        ";
        
        return $this->_db->fetchRow($sql, $nom);
    }

J'ai aussi commencé, après la lecture de pas mal de messages sur des FilteringSelect liées du style Pays => Ville,  à faire un peu de Javascript mais c'est là que je coince pour répondre à mon besoin.

infosperso.js :

Code:

function loadetablissement()
{
    // Nom de l'établissement choisi ou tapé
    var etbnom = dijit.byId('etb_id').getValue(); 
    
    // Coordonnées complètes de l'établissement
    var etablissement = new dojo.data.ItemFileReadStore({url: '/stagmas/public/accueiletudiant/getEtablissementOrigine/' + etbnom})
}

CustonQueryReadStore.js :

Code:

dojo.provide("custom.CustomQueryReadStore")
dojo.require("dojox.data.QueryReadStore")
dojo.declare(
    "custom.CustomQueryReadStore",
    dojox.data.QueryReadStore,
    {
        fetch: function(request)
        {
            request.serverQuery = {q: request.query.name};
            return this.inherited("fetch", arguments);
        }
    }
);

Il faudrait en gros que ma fonction Javascript loadetablissement :
a) Cherche l'établissement saisi ou sélectionné dans la table des établissements ;
J'ai cru comprendre qu'avec un Combobox, on récupère le libellé choisi ou sélectionné mais pas l'id sélectionné. La requête doit donc opérer sur le nom de l'établissement, en espérant qu'il n'y en ait pas deux du même nom, au lieu de l'identifiant sélectionné. À moins qu'il existe une fonction magique permettant de récupérer l'id si c'est bien une sélection et non un ajout dans la combobox ?
b) Si l'établissement existe :
b1) Masque les éléments de saisie de l'adresse et du téléphone,
b2) Affiche à la place l'adresse de l'établissement, récupérée par la requête getEtablissementParNom du modèle ;
c) Si c'est un nouvel établissement, on ne fait rien, ce sera traité lors de l'envoi du formulaire.

Et là mes compétences en Javascript étant voisines de pas grand chose, je sèche un peu sur comment faire cela !

4) Besoin voisin sur le même formulaire
J'ai aussi des FilteringSelect pour la ville de résidence de l'étudiant et la ville où est situé son établissement d'origine.
Tant que je n'avais que deux villes dans la table pour tester, pas de problème. J'y ai importé les 36682 communes françaises et ça devient beaucoup moins agréable (plusieurs secondes de chargement du formulaire et parcours de la liste fastidieux avec autant d'éléments, même si l'auto-complétion fonctionne).

L'idée serait de ne charger le contenu des filteringselect que lorsque l'utilisateur y a tapé une première lettre et de n'afficher que les communes commençant par cette lettre. Ça réduirait grandement le contenu de la liste (maxi 6008 communes commençant par S) et donc devrait accélérer le chargement du formulaire.

Et là aussi, je sèche sur la méthode qui me semble voisine du besoin précédent : récupération d'un jeu de données sur action de l'utilisateur et alimentation d'un élément avec ce jeu de données.

Merci à ceux qui voudront bien m'aider sur ce besoin qui me semble assez classique mais pour lequel je n'ai pas trouvé de solution satisfaisante sur le web.

Hors ligne

 

#2 25-01-2011 13:24:55

CinePhil
Membre
Date d'inscription: 24-03-2010
Messages: 19

Re: [ZF 1.11] Dojo : Changer formulaire sur action de l'utilisateur

16 fois vu et zéro réponse...

J'essaie avec Jquery qui semble bien plus simple à mettre en oeuvre mais j'ai un message d'erreur quand je tape une première lettre.

Je précise de suite que j'ai aussi dans ce formulaire un ZendX_JQuery_Form_Element_DatePicker qui fonctionne parfaitement, ainsi qu'un autre ZendX_JQuery_Form_Element_AutoComplete avec un jeu de données plus petit que je peux charger en même temps que le formulaire et qui fonctionne très bien lui aussi.

Dans le formulaire, j'ai ceci :

Code:

// Celui qui fonctionne
$etablissement = new Application_Model_DbTable_Etablissement();
        $result = $etablissement->fetchAll();
        $liste_etablissements = array();
        $liste_etablissements[0] = '';
        foreach($result as $etb)
        {
            $liste_etablissements[$etb->etb_id] = $etb->etb_nom;
        }
        
        $etb_id = new ZendX_JQuery_Form_Element_AutoComplete('etb_id');
        $etb_id
            ->setLabel('Nom')
            ->setRequired(false)
            ->setFilters(array('StripTags'))
            ->setJQueryParams(array('source' => $liste_etablissements)); 

// Celui qui pose problème
$id_commune_etablissement = new ZendX_JQuery_Form_Element_AutoComplete('id_commune_etablissement');
        $id_commune_etablissement
            ->setLabel('Commune')
            ->setRequired(false)
            ->setFilters(array('StripTags'))
            ->setJQueryParams(array('url' => $baseurl.'/accueiletudiant/recherchecommunes',
                                    'minChars' => 1));

Dans le modèle Commune.php, j'ai créé cette fonction :

Code:

    public function getCommunesParDebutNom($debut)
    {
        $debut = $debut.'%';
        $sql = "
            SELECT cmn_id, cmn_nom 
            FROM tr_commune_cmn 
            WHERE cmn_nom LIKE :debut 
        ";
        return $this->_db->fetchAll($sql, array('debut' => $debut));
    }

Dans le contrôleur, j'ai créé cette fonction :

Code:

    public function recherchecommunesAction()
    {
        $request = $this->getRequest();
        $debut = $request->getParam('term');
        
        $commune = new Application_Model_DbTable_Commune();
        $result = $commune->getCommunesParDebutNom($debut);
        $this->_helper->autoComplete($result);

Le formulaire s'affiche rapidement mais j'obtiens l'erreur suivante quand je tape une première lettre dans la zone :

http://localhost/stagmas/public/accueiletudiant/recherchecommunes?term=L 500 Internal Server Error
   
Action Helper by name AutoComplete not found.

Je sens que je ne suis pas loin de la solution mais...

Hors ligne

 

#3 26-01-2011 11:39:29

CinePhil
Membre
Date d'inscription: 24-03-2010
Messages: 19

Re: [ZF 1.11] Dojo : Changer formulaire sur action de l'utilisateur

J'avance mais ce n'est pas encore tout à fait ça.

Grâce à ce tutoriel vidéo, j'ai modifié le code de la fonction recherchecommunes dans le contrôleur en mettant json à la place de autocomplete :

Code:

    public function recherchecommunesAction()
    {
        $request = $this->getRequest();
        $debut = $request->getParam('term');
        
        $commune = new Application_Model_DbTable_Commune();
        $result = $commune->getCommunesParDebutNom($debut);
        $this->_helper->json(array_values($result));

Je n'ai plus l'erreur et Firebug affiche bien les données Json récupérées lors de la saisie des caractères dans la zone... mais celle-ci n'affiche pas la liste ! sad

EDIT :
J'ai essayé de créer dans le modèle Commune la même fonction search que dans la vidéo mais Eclipse affiche des erreurs :

Code:

    public static function search($term)
    {
        $filter = function($commune) use ($term)
        {
            if(stristr($city, $term))
            {
                return true;
            }
            return false;
        }
        return array_filter(self::$communes, $filter);
    }

Eclipse n'accepte pas function et use du $filter :

syntax error, unexpected function et unexpected use

Dernière modification par CinePhil (26-01-2011 11:52:43)

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages