Comment intégrer un plugin jQuery dans un projet Symfony 1.2 ?
La réponse à cette question ne pouvant pas tenir dans le modeste blog de Lexik.fr, je vais seulement vous expliquer comment intégrer la modification d’un champ « INPUT » en ajax dans un formulaire Symfony 1.2, à l’aide du plugin jQuery JEditable.
A ce stade, je vous recommande ce lien : JEditable
Pré-requis
- Comme d’habitude, l’éternel plugin : sfFormExtraPlugin
-
Les JS :
- jquery-1.3.2.min.js
- jquery.jeditable.js
Le widget
Chemin :
[votre_projet]/plugins/sfFormExtraPlugin/lib/widget/sfWidgetFormInputEditInPlace.class.php
Code source :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <?php class sfWidgetFormInputEditInPlace extends sfWidgetFormInput { public $object; public $route; public function __construct($option = array(), $messages = array(), $object = null, $route = null) { parent::__construct($option, $messages); $this->object = $object; $this->route = $route; } public function configure($options = array(), $messages = array()) { parent::configure($options, $messages); } public function render($name, $value = null, $attributes = array(), $errors = array()) { $prefix = $this->generateId($name); return sprintf(<<<EOF <b id="%s">%s</b> <script type="text/javascript"> $(function() { $("#%s").editable( "%s", { indicator : 'Saving...', type : "text", submit : "OK", style : "inherit", id : 'ajaxfield_id' }); }); </script> EOF , $prefix, $value, $prefix, url_for($this->route, $this->object, array('absolute'=>true)) ); } } |
Pour ce widget, j’ai créer 2 attributs.
- object
Cet attribut contient l’objet de la route objet Symfony.4
public $object;
- route
Cet attribut contient le nom de la route objet Symfony.5
public $route;
Ces attributs nous permettent de générer l’URL de la page qui va valider et éventuellement sauvegarder les données postées par le widget JQuery.
36 | url_for($this->route, $this->object, array('absolute'=>true)) |
Maintenant que l’outil est créé, utilisons le !
Toute la suite de l’article n’est qu’un exemple d’utilisation.
Schéma
Person:
columns:
firstname:
type: string(255)
lastname:
type: string(255)
email:
type: string(255) |
Routing
- show_person
La route du formulaire. - save_person_eip
Route de l’action « executeSaveEIP » qui valide et sauve les champs du modèle « Person »
# Route du formulaire
show_person:
url: /person/show/:id
class: sfDoctrineRoute
options: { model: Person, type: object }
param: { module: person, action: show }
# Route de la page sauvant les données postées en ajax
save_person_eip:
url: /person/saveEIP/:id
class: sfDoctrineRoute
options: { model: Person, type: object }
param: { module: person, action: saveEIP }
requirements:
id: d+
sf_method: [post] |
Actions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | // L'action pour le formulaire de base public function executeShow(sfWebRequest $request) { $this->person = $this->getRoute()->getObject(); $this->form = new PersonForm($this->person); } // L'action qui traite le post en ajax public function executeSaveEIP(sfWebRequest $request) { // Récupération de l'objet de la route $this->person = $this->getRoute()->getObject(); // Récupération des données postées par le widget JQuery $id = $request->getParameter('ajaxfield_id'); $this->value = $request->getParameter('value'); // Récupération du nom du champ if(ereg("person_(.*)$", $id, $key)) { $champ = $key[1]; } // Instanciation d'un formulaire lié à notre objet $form = new PersonForm(); // Récupération du validateur du champ $validator = $form->getValidator($champ); // On tente de valider le champ try { $cleaned = $validator->clean($this->value); $this->person->set($champ, $this->value); $this->joueur->save(); } catch(sfValidatorError $e) { // Erreur lors de la validation du champ // La valeur à afficher dans le template doit être la valeur actuelle de l'objet $this->value = $this->person->get($champ); } } |
Templates
- showSuccess.php
<h1>Edition d'une personne</h1> <?php echo $form['firstname']->render();?><br> <?php echo $form['lastname']->render();?><br> <?php echo $form['email']->render();?><br>
- saveEIPSuccess.php
<?php echo $value ?>
Formulaire
- On construit chacun des widgets avec l’objet et le nom de la route.
- On définit les validators.
public function configure() { // Widgets $this->widgetSchema['firstname'] = new sfWidgetFormEditInPlace(array(), array(), $this->getObject(), 'save_joueur_eip'); $this->widgetSchema['lastname'] = new sfWidgetFormEditInPlace(array(), array(), $this->getObject(), 'save_joueur_eip'); $this->widgetSchema['email'] = new sfWidgetFormEditInPlace(array(), array(), $this->getObject(), 'save_joueur_eip'); // Validators $this->validatorSchema['firstname'] = new sfValidatorString(); $this->validatorSchema['lastname'] = new sfValidatorString(); $this->validatorSchema['email'] = new sfValidatorEmail(); } |
View.yml
[...] default: javascripts: [jquery-1.3.2.min.js, jquery.jeditable.js] [...] |

Petite faute d’orthographe :s
Pour ce widget j’ai créé 2 attributs …
On notera aussi qu’il faut passer à jQuery l’id qui va être utilisé pour le POST.
id : ‘ajaxfield_id’
Car par défaut, celui-ci vaut « id » et Symfony utilise la même valeur pour la route objet.
Dans le paragraphe « Formulaire » le nom de la classe n’est pas bon.
J’ai changé le nom de « sfWidgetFormEditInPlace » vers « sfWidgetFormInputEditInPlace » car la classe ne gère que les champs « INPUT », il serait donc intéressant d’implémenter le textarea.
Dans la catégorie des choses qu’il reste à faire il y a aussi la configuration du plugin jQuery pour par exemple :
– rajouter un gif animé loading.gif
– utiliser les effets graphiques de jQuery