Voici pourquoi... Tout est d'une simplicité enfantine et instinctive.
Ainsi pour faire quoi que ce soit, il y a toujours une solution évidente et facile.
Voici le tuto pour appeller une action Symfony en Ajax par JQuery.
Tout d'abord, créons un contexte.
1.L'utilisateur clique sur un bouton.
2.Cela déclenche un évenement JQuery et donc une fonction.
3.Cette fonction envoit des données telle adresse (reliée à une action)
4.L'action éffectue une tache quelconque comme un test de valeur et renvoit la réponse
1.L'utilisateur clique sur un bouton.
Voici un code HTML très simple pour simuler ceci.
<input id="mybutton" type="button" value="Valider">2.Cela déclenche un évenement JQuery et donc une fonction.
<input id="mybutton" type="button" onclick="myAjaxFunction()" value="Valider">#myJSFile.js
function myAjaxFunction(){}
#myJSFile.js
function myAjaxFunction(){
var value = $("#myhiddenvalue").val();
$.post("myModuleName/myAction",
{myParam : value},
function(data)
{
$("#mybutton").attr("value",data);
});
}
4.L'action éffectue une tache quelconque comme un test de valeur et renvoit la réponse
public function executeIndex(sfWebRequest $request)
{
if ($request->isXmlHttpRequest())
{
$myValue = $request->getParameter('myParam');
if($myValue==1)
{
if ($request->isXmlHttpRequest())
{
$myValue = $request->getParameter('myParam');
if($myValue==1)
$message = "super";
else
$message = "bof";
return $this->renderText($message);
}
}
}
Ainsi, le texte du bouton va changer grace à un appel AJAX.
Passez plus de paramètres, renvoyez au lieu d'un texte un fichier _myFileToDisplay.php (renderPartial au lieu de renderText)
exemple :
return $this->renderPartial('myModuleNamle/myFileToDisplay', array('message' => $message,'hello' => "coucou"));
Pensez que lorsqu'on fait un renderPartial, le fichier doit commencer par underscore, soit ici _myFileToDisplay.php
Bonne chance
J'ai essayé renderPartial avec un formulaire(que je veux basculerle statut de ses champs entre non required et required en chochant ou décochant un checkbox), mais ça n'a pas l'air fonctionner .. j'ai pu vérifier que tout le traitement précédant renderPartial fonctionne super bien .. j'ai pensé que renderPartial ne fonctionne plus de la même manière dans symfony 1.4 .. mais c à vérifier
RépondreSupprimerLes formulaires sont des objets sous symfony, alors si tu veux l'utiliser, fait une page _myForm.php que tu va afficher avec un render_partial en passant ton $form et dans ton render partial tu fait : echo $form;
RépondreSupprimerDonc essaye ca :
return $this->renderPartial('myModuleNamle/myForm', array('form' => $form));
merci pour ta réponse Leny!
RépondreSupprimerc'est exactement ça ce que j'ai fait ..
apparemment j'ai quelque chose qui ne va pas quelques parts .. mais ça me rassure que tu confirmes que c'est ça la méthode qui marche!
Je continue mes 'investigations'
encore merci !
de rien :) tu n'a pas de message d'erreur ??
RépondreSupprimernon .. mais rien ne se passe
RépondreSupprimerJ'ai vérifié qu'avant l'appel à renderPartial tout se passe bien , fin normalement tout est prêt et ne reste que la revalidation du formulaire .. mais renderPartial en sois ne change rien dans l'interface ..
pour le moment j'ai fait autrement (changer en client si le user coche la case et au submit je vérifie selon la valeur de cette case, ça marche comme solution mais j'en suis pas très convaincu)
merci pour votre article
RépondreSupprimerpour mon cas , j'ai deux model auteur et livres
je vient d'imbriquer la formulaire du livre dans une formulaire d'auteur en utilisant ajax
mon problème que je n'arrive pas a récupérer l'objet du form auteur pour que je puisse créer un objet livre dans l'action exécuté lors de l'appel par ajax ??
pouvez vous SVP me donner quelque détails !!
Merci pour ton post qui m'a un peu aidé.
RépondreSupprimerje ne comprend pas à quoi sert
RépondreSupprimervar value = $("#myhiddenvalue").val();
Je ne vois pas d'élement HTML d'id myhiddenvalue....
Peut tu clarifier ce morceau de code merci :)
Salut "Anonyme",
RépondreSupprimerTu es d'accord avec moi j'imagine, le but est d'appeler une méthode. Tu devra souvent passer des paramètres, par exemple si tu veux supprimer un objet, tu créé un bouton et un champ de type text caché avec une valeur assignée : <input type="text" value="$id"/>
la ligne que tu ne comprends pas existe simplement pour récupérer cet id, la valeur que doit prendre le paramètre que j'appelle ensuite myParam et que donc j'affecte la valeur value... Ensuite dans ta méthode executeIndex (dans l'exemple), tu récupert ce paramètre passé avec cette ligne : $myValue = $request->getParameter('myParam');
Donc voilà, c'est plutot facile, je veux envoyer un parametre, donc je récupert la valeur que je veux en javascript puis je poste à la bonne adresse en passant en parametre myParam puis je fais le traitement dont j'ai besoin dans ma méthode. J'espère que j'ai été clair.
Mon probleme c'est que je veux personnaliser les formulaires alors j'ai essayé en premier lieu d'éditer _edit_form de mon template et j'ai remplacé une zone texte par une liste déroulante le problème que la liste s'affiche mais la valeur choisit s'affiche pas aprés le sauvegarde vous pouvez m'aider svp?!!
RépondreSupprimerTu veux faire quoi au final ? Es tu sur qu'il n'y a pas une autre facon pour faire ca ?
RépondreSupprimerSi j'ai bien compris, mais je ne suis pas sur d'ou la première question, tu veux remplacer un champs texte par un select... mais ce select va chercher quoi ? ou alors il est statique. S'il doit être dynamique, c'est à dire se charger avec un autre modèle,il faut que tu changes le type de widget dans lib/form/base en remplacant sfWidgetInputText() par sfWidgetFormDoctrineChoice(array('multiple'=>true/false, 'model'=> 'yourModelName'). Normalement, il se génère tout seul avec doctrine lorsque tu fais ton schema et en faisant une liaison entre les 2 modèles.
soit, si ta liste déroulante est statique, il faut que tu modifie le validateur, de string tu le passe à sfValidatorDoctrineChoice(array('model' => $this->getRelatedModelName('monDeuxiemeModeleName'), 'required' => false))... J'espère que ca t'aidera si c'est ca ton probleme
C'est bon Leny j'ai resolu mon probleme merci pour ce tuto qui m'a bien aidé.
RépondreSupprimersigné Anonyme du 22 avril 2010 02:38 :)
Bonjour,
RépondreSupprimerJ'ai pu utiliser ton render partial sur mon formulaire symfony. Mais au submit, les deux champs "ajaxisés" sont soumis avec une valeur nulle. Je me fait donc jeter au bind par el Validator (ça fait super héros formulé comme ceci ^^).
Pour plus de détails voici comment j'ai procédé :
1.1/ première action : l'index
public function executeIndex(sfWebRequest $request)
{
$this->form = new myForm();
}
1.2/ Le formulaire myForm
public function configure()
{
$this->widgetSchema->setNameFormat('myForm[%s]');
$this->widgetSchema['start_date'] = new sfWidgetFormSelect(array('choices' => array()));
$this->widgetSchema['end_date'] = new sfWidgetFormSelect(array('choices' => array()));
//Year Table
$year1 = date("Y");
$year2 = $year1 - 1;
$year3 = $year1 - 2;
$year4 = $year1 - 3;
$choices = array($year1 => $year1,
$year2 => $year2,
$year3 => $year3,
$year4 => $year4);
$this->widgetSchema['year'] = new sfWidgetFormChoice(array('choices' => $choices,'expanded' => true,));
$this->setValidators(array('year' => new sfValidatorChoice(array('choices' => array_keys($choices))),
'start_date' => new sfValidatorDate(array('required' => true)),
'end_date' => new sfValidatorDate(array('required' => true))));
}
Mes champs start_date et end_date sont dépendants du champs year. Ils sont donc instanciés à vide pour être "ajaxisés" après le chois de l'année.
1.3/ Le template indexSuccess
Je ne vais pas tout mettre, j'ai peur de te souler avec du code inutile. Je ne met que ce que je juge essentiel : l'appel ajax.
<|form action="" method="post" class="formulaire">
<|span class="txt_error">renderGlobalErrors() ?>
<|fieldset>
<|legend>
renderHiddenFields() ?>
<|span class="txt_error">renderError() ?>
render(array('onChange'=>jq_remote_function(array(
'update'=> 'period_end',
'url'=>'myModule/getPeriodend',
'method'=>'get',
'with'=>'year=2010',))
)
)
?>
<|fieldset id="period_end">
2.1/ L'appel ajax est fait au choix de l'année, voici l'action correspondante. Note que je fais appel à un formulaire différent du premier : myForm2. Celui-ci héritant de myForm.
RépondreSupprimerpublic function executeGetPeriodend(sfWebRequest $request)
{
$this->forward404Unless($request->isXmlHttpRequest());
$form = new myForm2();
return $this->renderPartial('myModule/periodEnd', array('form'=>$form));
}
2.2/ Le formulaire myForm2
class myForm2 extends myForm
{
public function configure()
{
unset($this['year']);
$choices = array("2010-01-01","2010-01-02","2010-01-03","2010-01-04");
$this->widgetSchema['start_date'] = new sfWidgetFormSelect(array('choices' => $choices));
$this->widgetSchema['end_date'] = new sfWidgetFormSelect(array('choices' => $choices));
$this->validatorSchema['start_date'] = new sfValidatorChoice(array('choices' => array_keys($choices)));
$this->validatorSchema['end_date'] = new sfValidatorChoice(array('choices' => array_keys($choices)));
}
}
2.3/ Le partial _perioEnd :
<|legend>
renderHiddenFields() ?>
renderLabel('Start Date') ?>
<|span class="txt_error">renderError() ?>
<|br />
renderLabel('End Date') ?>
<|span class="txt_error">renderError() ?>
<|br />
3/ Résultat avant le submit :
RépondreSupprimerLes combo box start_date et end_date sont correctement remplis, l'année est bien sélectionnée.
4/ Submit :
C'est le drame ! Voici l'action submit
public function executeSubmit(sfWebRequest $request)
{
$this->form = new DebitMemoReportForm();
sfContext::getInstance()->getLogger()->info("Avant le bind");
$this->form->bind($request->getParameter($this->form->getName()));
if ($this->form->isValid())
{
//do stuff
return sfView::SUCCESS;
}
$this->setTemplate('Index');
return sfView::SUCCESS;
}
Voici ce que j'obtiens sur ma page web
Start Date
* Required.
End Date
* Required.
Je ne sais vraiment pas d'où cela viens. En plus dans la fénêtre debug (je suis en frontend_dev) view/form : j'ai bien tout mes paramètres dans le formulaire...
Si tu as une petite idée, je suis par avance, éternellement reconnaissant.
Aie, c'est assez spécial... C'est vrai que les formulaires sont assez compliqués... J'essaye de reproduire ton problème si je trouve, je te tiens au courant.
RépondreSupprimerbonjour,
RépondreSupprimerj'essaye actuellement de faire un appel ajax afin de récupérer mes données partiellement au chargement de la page grâce à Jquery sous Symfony 1.4.
Avant toute chose je précise que mon code ne fonctionne pas en environnement de production, mais FONCTIONNE lorsque je suis en dev. Ceci est dû au no_script_name dans settings.yml qui est à true dans l'environnement de prod et pas en dev.
j'effectue un appel ajax côté template avec du jquery tel que:
J'ai donc un appel de cette forme côté template:
$.ajax({
type : "GET",
url : "",
data : "id_item=X&pr_id=Y", //les valeurs X et Y sont des variables php à la base
success : function(data){
retour = data;
$('#mondiv').append(retour);
}
});
Mon url fait donc appel à la route suivante dans mon routing.yml
recup_poi:
url: /petitesregions/recup_poi/:id_item/:pr_id
param: { module: petitesregions, action: recup_poi }
après je fais un traitement dans l'action recup_poi, puis place le contenu dans un partial afin de le mettre au callback dans mon div.
s'il y a besoin de plus d explications je suis dispo... et perdu aussi, ça fait 2 jours que je bloque là dessus, je commence à dérailler.
Salut,
RépondreSupprimerJe n'ai pas trop compris ce que tu essaye de faire :S Si j'ai bien compris, tu as des petites régions et tu souhaite récupérer des coordonnées relatives à un poi. C'est ça ? Si tu peux, explique le contexte, quelle est l'erreur que tu obtiens, j'essayerais de t'aider :)
Bonjour Lilian,
RépondreSupprimerJ'ai exactement le meme problème que le tien :(
est ce que vous avez trouvé une solution pour ça?
Merci d'avance!
Bonjour a tous,
RépondreSupprimerCe billet date depuis deja quelque temps mais j'ose quand meme laissé mon commentaire ! :)
Tout d'abord merci car il m'a été tres utile !
J'ai rencontré un probleme dans le $.post de la fonction javascript. En effet au lieu de mettre simplement $.post("myModuleName/myAction",... j'ai du mettre $.post("http://monsite.truc.fr/myModuleName/myAction", ....
Est ce que tu aurais une explication a cela ? Est ce que cela vient du routing ? Est ce que de ton coté tu avais mis en place une route pour myModuleName/myAction ? (si oui peux tu me la préciser ?...)
A bientot et encore merci :)
je suis débutant en Symfony et je développe mon premier site le souci que j'ai c'est que j'utilise AJAX pour m'afficher un formulaire d'ajout d'un commentaire, j'utilise la méthode renderPartial() dans l'action concernée (new) alors que dans mon fichier security.yml du module j'ai spécifier
RépondreSupprimernew:
is_secure: true
quand j’accède directement via un URL ça me redirige vers mon formulaire d'authentification mais c'est pas le cas quand je passe via AJAX
N.B : j'utilise sfDoctrineGuardPlugin
merci d'avance !!
Excellent merci
RépondreSupprimer