Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 25-07-2013 12:36:06

criseconomix
Nouveau membre
Date d'inscription: 17-10-2012
Messages: 3

AjaxContext, Layout et jQuery: jQuery perd la mémoire!

Bonjour à tous,

je rencontre une difficulté que je peine à surmonter, alors je viens ici en quête d'un coup de main smile

Présentation de mon code

J'affiche à l'écran un formulaire via une requête ajax: ce formulaire est en partie constitué de listes déroulantes enrichies grâce au plugin JQuery "Chosen" (http://harvesthq.github.io/chosen/).

Voici l'aide de vue associée à cet élément de formulaire (à noter que l'aide de vue se charge d'ajouter les fichiers de la librairie Chosen au container jQuery):

Code:

[lang=php]<?php

require_once "ZendX/JQuery/View/Helper/UiWidget.php";

class Evz_JQuery_View_Helper_ChosenSelect extends ZendX_JQuery_View_Helper_UiWidget
{
    /**
     * Ensure ressources are only registered once
     * @var bool
     */
    protected $_ressourcesAreRegistered = false;
    
    /**
     * chosenSelect()
     *
     * @todo   Minimiser les scripts css et js
     * @todo   Implémenter l'événement RESET
     * @link   http://harvesthq.github.com/chosen/
     * @tutorial available options: allow_single_deselect / disable_search_threshold / no_results_text / width
     * @param  string $id
     * @param  mixed $value
     * @param  array $attribs
     * @param  string $options
     * @param  string $listsep
     * @return string
     */
    public function chosenSelect($id, $value = null, array $attribs = array(), $options = null, $listsep = '<br />\n')
    {   
        if ( ! $this->_ressourcesAreRegistered ) {
            $this->jquery->addJavascriptFile($this->view->baseUrl() . $this->jquery->pluginPath . '/chosen/chosen.jquery.min.js')
                         ->addStylesheet($this->view->baseUrl() . $this->jquery->pluginPath . '/chosen/chosen.css');
            
            $this->_ressourcesAreRegistered = true;
        }
        
        $id = $this->_normalizeId($id);
        
        $params = array();
        if ( isset($attribs['jQueryParams']) ) {
            $params = $attribs['jQueryParams'];
            unset($attribs['jQueryParams']);
        }
        
        $this->jquery->addOnLoad(sprintf(
            '%s("#%s").chosen(%s);',
            ZendX_JQuery_View_Helper_JQuery::getJQueryHandler(),
            $id,
            ZendX_JQuery::encodeJson($params)
        ));
        
        if ( array_key_exists('options', $attribs) )
            $options = $attribs['options'];
        
        if ( array_key_exists('listsep', $attribs) )
            $listsep = $attribs['listsep'];
        
        return $this->view->formSelect($id, $value, $attribs, $options, $listsep);
    }
}

Du côté du controller, voici de quelle manière est servie le formulaire (il s'agit de l'action "fabrique" qui peut-être appelée avec ou sans ajax, d'où l'usage de l'aide d'action "AjaxContext"):

Code:

[lang=php]
<?php

class Commun_ModeleController extends Zend_Controller_Action
{
    /**
     * AjaxContext Helper
     * 
     * @var Zend_Controller_Action_Helper_AjaxContext
     */
    private $_ajaxContext = null;
    
    public function init()
    {
        $this->_ajaxContext = $this->_helper->getHelper('AjaxContext');
        $this->_ajaxContext->addActionContext('fabrique', 'html')
                           ->initContext('html');
    }

    public function fabriqueAction()
    {        
        if ( $this->_ajaxContext->getCurrentContext() == 'html' ) {
            $objet = $this->_getParam('objet');
            
            $form = $this->_getObject($objet);
            $form->addElement('hidden', 'objet', array('value' => $objet));
            
            $this->view->form = $form;
        } else {
            $request = $this->getRequest();
            
            if ( $request->isPost() ) {
                $objet = $request->getPost('objet');
                
                if ( $objet == 'interne' ) {
                    $this->_helper->flashMessenger->addMessage(Zend_Debug::dump($request->getPost()) . 'Agencement sauvegardé avec succès');
                } else {
                    $form = $this->_getObject($objet);
                    if ( $form->isValid($request->getPost()) ) {
                        $this->_helper->flashMessenger->addMessage(Zend_Debug::dump($form->getValues()) . 'Objet ajouté avec succés');
                    }
                }
                
                $this->_helper->redirector('fabrique');
            }
        }
    }
    
    private function _getObject($suffix, $type = 'form')
    {
        switch ( $type ) {
            case 'form':
                $class = 'Commun_Form_Modele_';
                break;
            case 'model':
                $class = 'Commun_Model_DbTable_Modele_';
                break;
            default:
                throw new Zend_Exception(sprintf('Type %s is unknown', $type));
        }
        
        $class .= ucfirst($suffix);
        
        if ( ! class_exists($class) )
            throw new Zend_Exception(sprintf('Class %s does not exist', $class));
        
        return new $class;
    }
}

Et voici le script de vue associé à l'action "fabrique" lors d'une requête de type ajax (fabrique.ajax.phtml):

Code:

[lang=php]
<?php

echo $this->jQuery(); // <----- Affichage de l'helper jQuery

echo $this->form;

Description du résultat attendu

Lors de l'appel à l'action "fabrique" via ajax, l'aide d'action "AjaxContext" se charge de désactiver le layout.
Habituellement l'aide de vue jQuery est affichée dans mon layout: pour ce cas particulier d'un appel ajax où la layout doit être absent de la réponse j'affiche donc l'helper jQuery dans mon script de vue (indispensable pour la librairie "Chosen" utilisée dans mon formulaire).

Globalement tout fonctionne à merveille: le formulaire est correctement appelé, le controller répond comme il se doit. Le pépin est le chargement de la librairie "Chosen": les listes déroulantes de mon formulaire ne sont pas chosen-ifiées...

On en vient maintenant à mon problème

l'helper jQuery ne renvoie rien du tout!. Il devrait contenir les fichiers js et css de "Chosen" mais ce n'est pas le cas (d'où le titre jQuery perd la mémoire): un dump de l'objet jQuery confirme que les fichiers de chosen y sont effectivement absents.
Mais si j'indique à l'aide d'action AjaxContext de conserver le layout bizarrement l'helper jQuery retrouve toute sa mémoire.

Je ne comprend pas le lien entre le layout et l'helper jQuery.
Si par hasard l'un d'entre vous se sent plus inspiré que moi... je suis tout ouïe smile

Merci beaucoup!

PS - un lien vers le post d'une personne ayant eu le même soucis que moi:
http://forums.zend.com/viewtopic.php?f=69&t=53288

Dernière modification par criseconomix (25-07-2013 16:04:37)

Hors ligne

 

#2 25-07-2013 18:32:51

criseconomix
Nouveau membre
Date d'inscription: 17-10-2012
Messages: 3

Re: AjaxContext, Layout et jQuery: jQuery perd la mémoire!

Bon eh bien je suis tout penaud mais néanmoins content car j'ai trouvé la solution!

Attention c'est du lourd

je reprend le code de mon script de vue

Code:

[lang=php]
<?php
 
echo $this->jQuery(); // <----- Affichage de l'helper jQuery
 
echo $this->form;

Solution

bon ben si j'inverse les deux lignes c'est gagné...

Code:

[lang=php]
<?php

echo $this->form;

echo $this->jQuery(); // <----- Affichage de l'helper jQuery

En effet c'est lorsque que la méthode "render()" de l'objet form est appelé que les helpers associés à chaque élément du formulaire sont exécutés... et pour mon cas le chargement de la librairie "Chosen" dans l'helper jQuery.

Voilà voilà, c'était trop simple pour que ce soit facile à trouver smile

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