Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 19-11-2009 14:55:52

__fabrice
Membre
Date d'inscription: 25-04-2007
Messages: 131

[jQuery] Communication entre Ajax et Zend

Hello à tous,

J'essaui de trouver des tuto au sujet de l'Ajaxcontext sans trop de succes. Je fais deja de l'Ajax avec jquery :
- Envoi d'une requete $.ajax({})  :

Code:

var email = input.attr('value');

$.ajax({
                type: "GET",
                url: url + 'newsletter/index/email/' + email,
                data: "",
                error: function(msg){
                    alert('Il y a eu une erreur lors de votre inscription à la newsletter.');
                },
                success: function(msg){
                    container.fadeOut('slow', function() {
                        var cssObj = {
                        'font-weight' : 'bold',
                        'color' : '#cc0000'
                        }
                        $(this).html("Votre inscription est validée.").css(cssObj).fadeIn('slow');
                    });
                }
            });

Par contre, je ne trouve pas comment communiquer avec le controller. C'est à dire par exemple, tester l'email dans le controller et le renvoyer a Jquery pour affichage.

Egalement, comment  recupérer dans la vue le resultat de jQuery ,au lieu de faire :

Code:

$(this).html("Votre inscription.....

, faire comme çà :

Code:

// $result vient de jquery.
$this->view->result = $result;

Merci à tous,
Fabrice

Hors ligne

 

#2 19-11-2009 15:49:59

r.monceau
Membre
Date d'inscription: 02-11-2009
Messages: 59

Re: [jQuery] Communication entre Ajax et Zend

Tu testes dans ton contrôleur de la même manière que tu appelles ton contrôleur sans requête Ajax à savoir par "http://tonsite/controller/view/"

Le retour de ton contrôleur doit cependant être différent puisqu'il ne va pas renvoyer une vue mais simplement les données que tu désires.
Pour ma part, j'ai redéfini un contrôleur pour les requêtes Ajax afin qu'il désactive mon layout et ma vue et qu'il définisse les données renvoyées.

Code:

public function preDispatch() {
    ...
    $this->_helper->layout->disableLayout();
    $this->_helper->removeHelper('viewRenderer');
    ...
}

public function postDispatch() {
    ...
    $this->getResponse()->clearBody();
    $this->getResponse()->setHeader('Content-Type', 'text/x-json');
    $this->getResponse()->setHeader('Charset', 'utf8');
    $this->getResponse()->setBody($this->_resultat);
    ...
}

J'ai une variable d'instance $_resultat en protected qui me permet de stocker ce que je désire renvoyer à ma vue après ma requête ajax. Ensuite, il ne me reste qu'à étendre mon contrôleur ajax en fonction de ce que je désire.

Voila j'espère avoir répondu à ta question. Dans mon cas, les données renvoyées sont en json et utf-8 mais tu peux faire autrement wink

Hors ligne

 

#3 19-11-2009 16:06:09

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [jQuery] Communication entre Ajax et Zend

Je te poste la partie PHP (je te laisse te débrouillé pour le code javascript)
Le but de ce code est qu'a partir d'une page web, on clique sur un bouton qui, en ajax, va supprimer un utilisateur d'une base (via son id)
L'action renverra du json avec une clé 'delete' ayant pour valeur true ou false

Code:

class UserController extends Zend_Controller_Action
{
  /* on prépare l'action 'info' a répondre au requête ajax et à renvoyé du json  */
  public function init()
  {
     $ajaxContext = $this->_helper->getHelper('AjaxContext');
     $ajaxContext->addActionContext('delete', 'json')->initContext();
  }
 

  public function deleteAction()
  {
     $id = $this->_getParam('id');
     /* code de suppression */
     $this->view->delete = true;
  }

et voila, c'est très simple
Il faut juste assuré que dans la requête ajax, tu es le format qui corresponde
par exemple :
http://localhost/user/delete/id/3format/json

Si tu ne mets pas format, la requête ne sera pas prise en compte comme requête ajax
Il est inutle de désactiver le layout, le viewrender. Initule de touché aux entête. L'aide AjaxContext s'occupe de tout ca

EDIT :
Dans le cas du json, pas besoin de fichier .phtml, car l'aide va récupérer les variables enregistré dans ta vue et les envoyés. Par contre, pour les autres type il faut la vue (pour du html, ca serait user/delete.ajax.phtml)

Dernière modification par nORKy (19-11-2009 16:11:34)


----
Gruiiik !

Hors ligne

 

#4 19-11-2009 16:09:18

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [jQuery] Communication entre Ajax et Zend

Bon, allez, je te donne un peu de code javascript smile

Code:

var deleteHref = 'http://localhost/user/delete/id/3/format/json';
$.getJSON(deleteHref, function(data) {
                     if (data.deleted == true) {
                         alert('youpi !!');
                     }
                     else {
                         alert('pas coule :-(');
                     }
                 });

Dernière modification par nORKy (19-11-2009 16:12:06)


----
Gruiiik !

Hors ligne

 

#5 19-11-2009 16:13:37

__fabrice
Membre
Date d'inscription: 25-04-2007
Messages: 131

Re: [jQuery] Communication entre Ajax et Zend

Merci merci.

J'essaie tout çà, et je vous fais un retour si j'ai un soucis.


Fabrice

Hors ligne

 

#6 19-11-2009 16:26:32

r.monceau
Membre
Date d'inscription: 02-11-2009
Messages: 59

Re: [jQuery] Communication entre Ajax et Zend

Effectivement merci beaucoup. J'ai pas mal de modifications à faire je crois mais le résultat est nettement plus propre à utiliser ^^

Hors ligne

 

#7 19-11-2009 16:38:19

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [jQuery] Communication entre Ajax et Zend

r.monceau a écrit:

Effectivement merci beaucoup. J'ai pas mal de modifications à faire je crois mais le résultat est nettement plus propre à utiliser ^^

Faut avouer que c'est pas facile à comprendre.
Mais une fois compris, c'est facile. Ainsi, pour une même action, on peut servir différent type de donnée.
Par exemple, pour servir des images en ajax, je fais comme ca :
(Le context "png" n'existant pas par défaut, je le créé)

Code:

$contextSwitch->addContext('png', array(
      'suffix' => 'png',
      'headers' => array(
        'Content-Type' => 'image/png',
        'Cache-Control' => 'no-cache, must-revalidate',
        'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
      )))
      ->addActionContext('graph', 'png')
      ->initContext();

Je créé un fichier graph.png.phtml (parce que j'ai défini comme suffix 'png') et je mais dans mes requête ajax format/png.
Ainsi, pour la même action, je peux fournir une image via une requête Ajax, format/png (via graph.png.phtml) ou alors une requete non ajax (on dira classique) via graph.phtml

Dernière modification par nORKy (19-11-2009 16:39:19)


----
Gruiiik !

Hors ligne

 

#8 20-11-2009 10:05:27

guychel
Nouveau membre
Date d'inscription: 18-11-2009
Messages: 5

Re: [jQuery] Communication entre Ajax et Zend

J'ai un pb similaire help me please !!!

Bonjour,

Désolé j'ai bien lu la documentation mais je ne comprend toujours pas très bien le fonctionnement de AjaxContext dans Zend.

En effet :

*J'ai en input date (datepicker) et une page d'horaire:(9h,10,11h par exemple ) et j'aimerai :

quand le user choisit la date à partir du calendrier que la fonction js envoie une requête xmlhttprequest avec la date selectionnée (11/09/2009 par exemple) au fichier de traitement (à definir) puis récupère la réponse envoyée(vérification s'il y a des dates disponibles pour la date choisie dans la bdd).

*après récupération de la réponse j'aimerai effacer le input des plages horaires et remplacer cette dernière par ma réponse provenant de la fonction js.(sans recharger la page mais juste la partie dynamique)

J'ai vraiment besoin d'aide un exemple assez proche m'aiderait beaucoup.

Merci d'avance.

Hors ligne

 

#9 20-11-2009 10:13:46

__fabrice
Membre
Date d'inscription: 25-04-2007
Messages: 131

Re: [jQuery] Communication entre Ajax et Zend

hello,

J'ai bien suivi l'exemple de nORKy (en #3). Par contre, j'ai bien une variable json qui est ecris dans mon HTML :

Code:

<div class="grid_16" id="content">
    {"deleted":"true"}        
</div>

Mais comment je le traite, je l'a récupère ?. Elle s'est rajouté à la place du content (page principale) de mon layout. Je n'ai pas de retour dans la fonction ajax :

Code:

var deleteHref = url + 'newsletter/index/email/' + email + '/format/json';
            $.getJSON(deleteHref, function(data) {
                alert(data);
                if (data.deleted == true) {
                    alert('youpi !!');
                }
                else {
                    alert('pas coule :-(');
                }
            });

Aucun alert ne se déclanche.

Merci
Fabrice

Hors ligne

 

#10 20-11-2009 12:45:24

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: [jQuery] Communication entre Ajax et Zend

Bonjour,

Quelques remarques sur le sujet.

Le plus propre et robuste, je pense, est d'utiliser les entêtes http et d'automatiser le système.

Lors d'une requête "Ajax" des entêtes précises sont envoyées dans la requête (si le framework JS n'envoie pas les entêtes, je conseille de le remplacer vite fait par un autre !). Entres autres l'entête 'Accept' est utilisée pour indiquer le type de données attendues en retour.

Le helper ContextSwitch choisit le contexte en fonction du paramètre "format" passé dans l'url. C'est très facile, grâce à un plugin de controller, de setter automatiquement le paramètre "format" en fonction du header 'Accept' de la requête.

Par ex. sur le "routShutdown()" du plugin :

Code:

$headerAccept = $request->getHeader('Accept');
switch(true) {
    case (strstr($headerAccept, 'application/json')) :
        $request->setParam('format', 'json');
        break;
    // etc. pour les autres types
}

Ensuite comme expliqué plus haut, il suffit d'ajouter les contextes appropriés aux actions concernées.
Mais une petite remarque quand même, à mon avis c'est le rôle de la vue d'afficher les données et d'envoyer la réponse appropriée, et bien sûr en settant les bonnes entêtes de réponse et notamment "Content-Type".

Par défaut, sur les contextes json l'auto-sérialisation du JSON est activée. Ça veut dire que toutes les variables passées à la vue sont automatiquement sérialisées en json dans la réponse, le view renderer est désactivé et la réponse est directement envoyée sur la sortie.
Or, d'autres variables peuvent avoir été assignées à la vue avant l'action dans laquelle on se trouve, ça peut donc polluer la réponse.

Par ex. je vais avoir en json dans la réponse :

Code:

{"viewBasePath":"D:\\website\\www\\test\\app\/..\/tpl\/","scriptsDirectoryName":"scripts","doctype":"XHTML1_STRICT","charset":"utf-8","scriptPaths":["sign","member","share"]}

Du coup, si par ex. je renvoie une listes d'items, il faudra assigner le résultat à une variable nommée précise dans la vue et JS devra connaitre cette information.
Je vais par ex. setter mon array d'items $this->view->items = $items->toArray(); et spécifiquement récupérer "items" côté JS.

Je conseille de désactiver l'auto-serialization grâce à:

Code:

$contextSwitch = $this->_helper->getHelper('ContextSwitch');
$contextSwitch->initContext();
$contextSwitch->setAutoJsonSerialization(false);

et de laisser le rôle d'afficher les données à la vue. Ce n'est pas parce qu'on ne vient pas d'un navigateur et qu'on ne demande pas du html qu'il faut laisser tomber le pattern MVC, la vue affiche les données.

Par ex. si je veux afficher une list d'items, il y aura pour une action "listAction" une vue list.json.phtml qui contiendra :

Code:

<?php
$this->response->setHeader('Content-Type', 'application/json');
echo $this->json($this->items);

Encore plus idéal, en fonction des actions, setter le code http de retour approprié et utiliser ce code pour réagir côté JS (500 > erreur, 400 (bad request) > erreur de validation de champs, etc. etc.).

De cette manière dans le body de ma réponse en JSON je n'aurai que mes items et non plus les autres variables qui polluent le résultat. C'est donc plus propre (surtout pour des webservices) et plus logique par rapport au pattern MVC.

Mes controlleurs restent génériques et ce sont mes vues qui décident, selon le contexte, ce qu'elles doivent afficher.


A+ benjamin.


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#11 22-11-2009 23:53:19

__fabrice
Membre
Date d'inscription: 25-04-2007
Messages: 131

Re: [jQuery] Communication entre Ajax et Zend

Merci "Delprog",

Ton explication certes tres interessante, me semble un brin compliqué. Il y a un chapitre (le 5) dans l'excellent livre "Zend Framework In Action". Je pense que je vais m'y attarder un peu.

Par contre, personne n'a donné un exemple tout simple pour l'ajaxContext sad

Fabrice

Hors ligne

 

#12 23-11-2009 10:02:21

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: [jQuery] Communication entre Ajax et Zend

Salut,

En fait c'est bien plus simple que ce qu'il parait. Je conseille tout simplement d'utiliser le protocole HTTP pour ce pour quoi il est fait, c'est à dire en échangeant les bonnes entêtes et les bons code http entre "Ajax" et le Serveur.

Pour ta question, pour ajouter des contextes il y a plusieurs méthodes, perso j'utilise la variable public "contexts" pour le ContextSwitch et "ajaxable" pour "AjaxContext" et ensuite dans l'init() de mes controllers j'initialise simplement le helper.

Ex. avec ContextSwitch, dans le controlleur:

Code:

public $contexts = array(
    'index' => array('json', 'xml'),  // indexAction()
    'trululu' => array('json')  // trululuAction()
);

// ...
public function init()
{
    parent::init();
    $contextSwitch = $this->_helper->getHelper('ContextSwitch');
    $contextSwitch->setAutoJsonSerialization(false)
                  ->initContext();
}

AjaxContext :

Code:

// attention le nom de la variable n'est pas le même
// qu'avec le ContextSwitch
public $ajaxable= array(
    'index' => array('json', 'xml'),  // indexAction()
    'trululu' => array('json')  // trululuAction()
);

// ...
public function init()
{
    parent::init();
    $ajaxContext= $this->_helper->getHelper('AjaxContext');
    $ajaxContext->setAutoJsonSerialization(false)
                ->initContext();
}

// ...

public function indexAction()
{
    $this->view->items = array('item1', 'item2', 'item3');
}

La différence entre le helper context et le helper ajaxContext est que dans le second, le context switch que si la requête est de l'Ajax (entête envoyée par le framework js), ZF teste ça automatiquement avec isXmlHttpRequest().

Pour la vue, tu ne peux pas mélanger deux types de format, sinon ton JSON ne sera pas lisible par JS.
index.json.phtml:

Code:

<?php $this->response->setHeader('Content-Type', 'application/json'); ?>
{"deleted":"true"}

Pour sérialiser le json dans la vue avec Zf, il existe un helper de vue "json"

Code:

<?php
$this->response->setHeader('Content-Type', 'application/json');
echo $this->json($this->items);

A+ benjamin.


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#13 23-11-2009 10:06:07

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [jQuery] Communication entre Ajax et Zend

__fabrice a écrit:

hello,

J'ai bien suivi l'exemple de nORKy (en #3). Par contre, j'ai bien une variable json qui est ecris dans mon HTML :

Code:

<div class="grid_16" id="content">
    {"deleted":"true"}        
</div>

Mais comment je le traite, je l'a récupère ?. Elle s'est rajouté à la place du content (page principale) de mon layout.

tu as du faire une erreur dans la déclaration de ton contexte. Car, c'est du html qui arrive dans le cas que tu me montre, pas du json (certes il y en as, mais a priori, ton layout a été désactivé, mais pas le rendu de ta vue)


----
Gruiiik !

Hors ligne

 

#14 01-12-2009 13:41:41

guychel
Nouveau membre
Date d'inscription: 18-11-2009
Messages: 5

Re: [jQuery] Communication entre Ajax et Zend

Comment récupérer la réponse d'une view par l'intermédiare du controller renvoyée via une fonction ajax après un select?

J'ai du mal help me please!!!

Merci

Hors ligne

 

#15 07-12-2009 13:59:26

nORKy
Membre
Date d'inscription: 06-03-2008
Messages: 1098

Re: [jQuery] Communication entre Ajax et Zend

Tu peux répéter la question ?


----
Gruiiik !

Hors ligne

 

#16 07-12-2009 14:57:17

r.monceau
Membre
Date d'inscription: 02-11-2009
Messages: 59

Re: [jQuery] Communication entre Ajax et Zend

Hum je suis pas sûr de bien avoir saisi non plus mais s'il s'agit de récupérer les paramètres envoyés, tu peux faire "$this->getRequest()" au niveau de ton contrôleur.

Hors ligne

 

#17 07-12-2009 19:00:19

__fabrice
Membre
Date d'inscription: 25-04-2007
Messages: 131

Re: [jQuery] Communication entre Ajax et Zend

hello,

Si çà peut aider, voici un exemple simple mais concret  avec ZF (AjaxContext) et JQuery tiré de l'excellent libre "ZF in Action"  :

Code:

class IndexController extends Zend_Controller_Action {

    function init()    {
        $ajaxContext = $this->_helper->getHelper('AjaxContext');
        $ajaxContext->addActionContext('feedback', 'json');
        $ajaxContext->initContext();
    }

    public function feedbackAction() {
        $id = (int)$this->_request->getParam('id');
        $helpful = (int)$this->_request->getParam('helpful');

        $this->view->result = true;
        $this->view->id = $id;
        $this->view->helpful_yes = ($helpful ? "yes" : "no");
        $this->view->helpful_total = 999999;
    );
}

la ligne suivante :ajaxContext->addActionContext('feedback', 'json'); fait référence au fichier qu'il faut créer feedback.json.phtml :

Code:

<?php
    echo get_object_vars($this);
?>

list.phtml :

Code:

 ...
<a href="#" id="<?php echo '1'. '|'. 10 .'|' . $this->baseUrl(); ?>">Yes</a>
<a href="#" id="<?php echo '0'. '|'. 11 .'|' . $this->baseUrl(); ?>">No</a>
...

le js :

Code:

$(document).ready(function() {

    $('.helpfullAjax a').click(function() {

        var params = $(this).attr('id');
        param = params.split('|');
        var response = param[0];
        var id = param[1];
        var baseUrl = param[2];

        var sUrl = baseUrl + "/index/feedback/format/json/id/" + id + "/helpful/" + response;

        $.ajax({
            url: sUrl,
            global: false,
            type: "GET",
            dataType: "json",
            success: function(json){
                $('#response-jquery').html(json.helpful_yes);
            },
            error : function (msg) {
                console.warn('error : ' + msg);
            }
        });

    });

});

En fait, le JS fait appel, en Ajax, à l'action feedbackAction(), qui peut modifier aussi sa vue. Du coup, ces valeurs :

Code:

        $this->view->result = true;
        $this->view->id = $id;
        $this->view->helpful_yes = ($helpful == 1 ? "yes" : "no");
        $this->view->helpful_total = 999999;

sont récupérables par le retour de l'ajax:

Code:

success: function(json){
                $('#response-jquery').html(json.helpful_yes); //$this->view->helpful_yes = ($helpful == 1 ? "yes" : "no");

            },

Fabrice

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