Dégradabilité javascript et Ajax dans Symfony avec jQuery
Par NiKo le mercredi 3 octobre 2007, 11:31 - Dev
- Lien permanent -
16 commentaires -
Tags :
Pour un projet, je suis en train d'utiliser la librairie javascript jQuery dans Symfony, en lieu et place du couple prototype et scripaculous dont je vous avait déjà parlé.
L'idée est ici de ne pas avoir à utiliser les helpers fournis par Symfony (qui mettent en oeuvre exclusivement Scriptaculous) et ainsi d'éviter d'utiliser les deux librairies simultanément sur le projet, mais aussi de décoreller le code javascript des templates et de favoriser une meilleure dégradabilité de ce dernier.
Par exemple, au lieu d'utiliser la fonction link_to_remote() dans notre template, on peut tout à fait imaginer d'employer un bon vieux link_to() des familles et de lui appliquer une classe css qu'on va pouvoir cibler depuis jQuery afin d'effectuer un appel AJAX pointant vers l'url présente dans l'attribut href du lien. Avec un exemple, c'est un peu plus clair :
<?php echo link_to('Mon lien', '@maroute?monparam=mavaleur', array('class' => 'ajax_link')) ?>
Dans un fichier javascript (jQuery doit bien entendu être chargé) :
$(document).ready(function() { $('a.ajax_link').click(function() { $.ajax( { type: 'post', url: $(this).attr('href'), success: function(msg) { alert("Résultat: " + msg); } }); return false; } ); });
Avantage supplémentaire, vous continuez à bénéficier du système de routing Symfony (pas d'urls en dur dans les fichiers javascripts externalisés.)
Là où Symfony va également nous aider, c'est au travers de sa gestion native de la décoration d'une vue en fonction du type d'appel HTTP : le framework va detecter si l'action a été appelée ou non depuis une requête XmlHttpRequest et, si c'est le cas, décorer la vue avec le layout global de l'application et donc présenter à vos utilisateur le résultat escompté, qu'ils aient activé javascript ou non pour surfer sur votre site.
Si vous désirez mettre à jour un élément de l'arbre DOM avec le contenu reçu d'une requête Ajax, voici une autre petite astuce ; on va utiliser une ancre dans l'url et s'en servir comme argument décrivant l'id DOM qu'on veut mettre à jour :
<?php echo link_to('Mon lien', '@maroute?monparam=mavaleur#mon_div', array('class' => 'ajax_link')) ?> <div id="mon_div" style="display:none"></div>
Et en javascript :
$(document).ready(function() { $('a.ajax_link').click(function() { var href = $(this).attr('href'); var target = href.substring(href.lastIndexOf('#'), href.length); $.ajax( { type: 'post', url: href, success: function(msg) { if ($(target)) { $(target).html(msg).show('slow'); } } } ); return false; } ); });
Note : on aurait pu aussi détourner l'attribut target à cette fin mais ce dernier n'est pas valide en XHTML strict.
Bien entendu, ceci n'est qu'un microscopique aperçu de l'étendu des possibilités de jQuery et de son intégration possible avec Symfony (ou d'autre frameworks et langages, bien entendu.)
16 commentaires (Ajouter un commentaire)
Je viens de découvrir un nouveau plugin 'sfJqueryPlugin' disponible sur le site de sf ,je l'ai testé et ca fonctionne parfaittement.
C'est concu pour remplacer les helpers Javascript dans le but de ne plus utiliser prototype en faveur de jQuery.
Pour exemple, on peut utiliser link_to_remote() avec Ajax si on remplace la methode par jq_link_to_remote() et ca fonctionne en toute transparence.
reSalut !
Bon alors j'ai mis la main à la pâte et j'ai essayé, après avoir fait quelques recherches infructueuses sur Google-mon-ami. Tu es donc tel Obiwan Kenobi, mon seul espoir !
Soyons concret : j'ai une page qui affiche une actu et il y a les commentaires en dessous, affichés par page. Comment d'un seul coup gérer le avec-javascript et le sans-javascript pour ce changement de page?
En effet, nos deux compères proviennent de deux modules différents sous Symfony : donc si je met comments/show dans le href du lien, si javascript est activé, je peux rafraichir une div très aisément grâce à jquery, mais si javascript n'est pas activé je me retrouve sur la page comments/show, cad sans la petite news avec...
Ce n'est pas ce que nous voulons. Pourrais-tu m'éclairer voire me donner quelques pistes ?
Très intéressant comme article et les commentaires aussi.
Je m'intéresse de très près à des "actions" avec symfony, codées une seule fois, qui donnerait le même résultat au visiteur qu'il ait javascript intégré (dans ce cas avec ajax et un rafraichissement partiel de la page) ou pas (dans ce cas rafraichissement complet de la page). En somme ce qu'explique une partie de l'article et ce que dit Nath.
Pourrait-on avoir plus de détails ? Au niveau des templates... En bref, comment mettre ça en place en pratique, car là, ça m'apparait encore un peu sombre (ça fait une semaine que je symfonise).
Olivier@gt; Bof, je pense qu'il y aurait plus à creuser pour un post sur le blog de Clever.
article vraiment bien, il aurait tout à fait sa place sur un autre blog
Merci du conseil
Mais ce n'est pas tant la détection d'une requete via XHR (au pire, suffit de rajouter un paramètre).
Non, c'est surtout comment ré-afficher la bonne page avec les changements qu'auraient fait JS.
J'avais commencé à regarder les manipulations DOM de PHP, mais je n'ai pas eu le temps de finir ma recherche. Je dois m'y remettre dès que j'ai terminé ma mission en cours. Il y a peut-être une solution simple.
@krachot: De rien, c'est surtout les devs de Symfony qu'il faut remercier
Je me suis inscrit pour la preview de del.icio.us, j'ai hâte de voir ce que ça donne également.
@Niko: si tu trouves ça vraiment interressant, tu peux voir un exemple sur ce site, qu'on vient de mettre en ligne: http://www.bebe9.com/.
Le principe est vraiment bon, et j'espere que pour la prochaine version de symfony (1.5 ou 2.0 ?!!), les développeurs de sensio remplacent prototype et scriptaculous par UJS et PJS.
Surtout que maintenant jQuery possède jQueryUI et n'a donc plus rien à envier à prototype
Sinon c'est l'occas de te remercier de m'avoir fait découvert ce fabuleux framework l'année dernière. J'ai réussi à l'imposer dans ma boite et honnetement, ce n'est que du bonheur. J'ai d'ailleurs hate de voir le nouveau del.icio.us...
Chef ! Oui, chef !
pas ce soir !
@krachot: Hmmm, intéressant, je connaissais pas cette possibilité. Je vais regarder ça de plus près
@Niko: Le mieux avec UJS, et c'est comme ça que je m'en sers, c'est de ne pas utiliser les helpers fournis. Tu mets ton code jquery entre les balises UJS_block/UJS_end_block, et hop à l'affichage ton code javascript à disparu de ton HTML et se retrouve dans un fichier javascript à part, grâce à PJS.
@Navid: Thanks for pointing at your plugin which I didn't knew. As I'm not really fond of XML configuration files, I'll stick at my current approach but it's here just matter of taste
@Nath: Symfony ajoute un en-tête spécial à la requête pour identifier les requêtes Ajax, tu devrais regarder de plus près cette approche, ça peut donner des idées.
@krachot: UJS me fout des balises au milieu du code HTML et ça, ça me froisse, même si cela reste totalement non-obstrusif je te l'accorde.
Il faut aussi noter que le plugin UJS (http://trac.symfony-project.com/wik...) permet d'utiliser les même helpers de prototype avec jQuery et ainsi de produire du code javascript non-intrusif.
Pour l'avoir utiliser sur plusieurs projets avec le plugin PJS (http://trac.symfony-project.com/wik...), je peux t'assurer que cela simplifie énormément le développement javascript.
Tiens c'est marrant, moi qui m'intéresse plus au Zend Framework (je sais pas pourquoi j'ai du mal avec Symfony), je cherchais une technique similaire.
Pour identifier le conteneur cible, j'avais pensé à mettre un champ caché dans la vue. Mais ton idée d'utiliser une ancre est surement plus flexible.
Par contre, il me reste à trouver un moyen pour que PHP prenne le rôle d'AJAX si celui-ci est absent.
Bonjour,
excuse me for writing in english, but the last time I spoke it was on the 11th grade in school
I could write that all in french but that you would see a lack of many accents and it would take me half an hour and would still consist of mistakes
I have an proposal for you: Use the sfTaconitePlugin I wrote, where you can just define a XML file to handle the response. This XML file is parsed and breaks down the tags into jquery-commands so you can update even multiple DOM elements with it. If you want to take a look http://trac.symfony-project.com/wik...