Bonjour,
je souhaite mettre en place un filtre de données via un système de checkbox.
Je souhaiterais faire ce filtre en ajax.
Voici ma vue : 3 checkbox classique avec des données tirées d'une base de données (elle même contenant 3 lignes tirées de mon imagination)

<?php 
//crée le formulaire d'id ArticleIndexForm
echo $this->Form->create();
foreach($categories as $key=>$category):
    echo $this->Form->input($category, array('type'=>'checkbox', 'value'=>$category, 'class'=>'ajaxInput'));
endforeach;
echo $this->Form->end();
?>

J'essaie d'émettre une requête ajax afin de récupérer les data des checkbox à chaque fois que je clic dans mon formulaire (qui ne contient que ces checkbox), voici le code javascript :

$('#ArticleIndexForm').on('click',function(){
        var data = $('#ArticleIndexForm').serialize();
        $.ajax({
            type: "POST",
            url:"index",
            cache: false,
            data:data,
            datatype:"json",
            success: function(data){
                alert(data);
            }
            error : function(data){
                alert('petits soucis dans ton ajax');
            }
        });
    });

Ce code ne s'exécute pas, j'ai essayé plusieurs choses, au mieux j'ai réussi à remplacer le contenu de ma page par le même contenu, mais je n'ai jamais réussi à passer de données.

Pourriez vous m'éclairer sur le passage de données en ajax ?

N'hésitez pas à me poser des questions si ce post n'est pas assez clair.

Merci,

Piverte

13 réponses


amethyste
Réponse acceptée
$('#ArticleIndexForm :checkbox').on('click',function(){
      //recupère toutes les checkbox cochées
      var categories = $('#ArticleIndexForm input:checked').map(function() {
        return this.value;
      }).get().join();
      //debug categories selectionnées
      console.log(categories);
      //requête
      $.post("./controller/action", categories,
        function(data){
          console.log(data);
        });
    });
Piverte
Auteur
Réponse acceptée

Je viens de trouver la solution à mon problème :
Le format de data envoyé vers le serveur doit être du type : data: cle1=value1&cle2=value2...
J'espère que cela aidera d'autres personnes

Piverte
Auteur

Merci amethyste pour ta réponse !
Après avoir regardé la documentation jquery je ne suis pas sur d'avoir saisi toute la subtilité de la fonction qui récupère les categories.
La fonction map permet de mettre les "value" des checkbox sous forme de tableau c'est bien ça ? Ensuite tu récupères ces valeurs avec la méthode get et tu les mets sous formes de liste avec join ?

Je ne connaissais pas le fonctionnement du console log -_- je l'ai découvert grâce à toi.

En ce qui concerne la syntaxe de $.post j'ai du mal à comprendre l'url car chez moi ça ne fonctionne pas pareil j'ai l'impression.
lorsque j'écris "./controller/action", ça me donne une url du type /controller/controller/action.
Du coup je suis obligé d'écrire uniquement l'action pour avoir ce que je veux. Est-ce normal ?

Y-a-t-il une raison particulière pour avoir utiliser $.post plutôt que $.ajax ?
Je pensais récupérer les données en json (option disponible uniquement avec $.ajax si je ne me trompe ?), mais ce n'est peut être pas nécessaire après tout vu que je peux ré-afficher le code HTML directement.

Dernière question, comment j'accède côté serveur (controleur) à ces données, j'ai testé une petite écriture en session pour voir mais il semblerait que je ne cherche pas mes données au bon endroit.

$this->Session->write('ajax',$this->request->data)
debug($this->Session->read('ajax'));

En tout cas merci pour cette réponse extrêmement précise, ça fait 3 jours que je galère sur ce problème.

Merci encore !

La fonction map permet de mettre les "value" des checkbox sous forme de tableau c'est bien ça ? Ensuite tu récupères ces valeurs avec la méthode get et tu les mets sous formes de liste avec join ?

exactement :-) Mais je viens de me rendre compte que tu peux laisser les categories sous forme array donc .join() pas obligatoire

En ce qui concerne la syntaxe de $.post j'ai du mal à comprendre l'url

Oui c'est normal. Perso quand je commence à faire l'ajax en local je crée un virtualHost sur apache du genre monsite-en-dev.local pour ne pas avoir de surprise en prod aux niveau des urls

y-a-t-il une raison particulière pour avoir utiliser $.post plutôt que $.ajax ?

Aucune, sinon d'avoir un peu moins de code à taper. $.post est le raccourci de $.ajax({type: "POST"});

Il est effectivement préférable que tu envoies les données en json, à préciser dans le 4eme paramètre de $.post

$.post("./controller/action", categories,
    function(data){
      console.log(data);
    },
    'json'    
);
Piverte
Auteur

Ok, super, tes réponses me font beaucoup avancer ! :)

Je viens de voir que tu avais répondu avant que j'edit mon post, donc je réécris ma dernière question.

Comment j'accède côté serveur (controleur) à ces données, j'ai testé une petite écriture en session pour voir mais il semblerait que je ne cherche pas mes données au bon endroit.

$this->Session->write('ajax',$this->request->data)
debug($this->Session->read('ajax'));

Encore merci de ton aide extrêmement efficace !

Dans ton controller, dans la fonction qui reçoit les données en POST :

//exemple dans ProduitsController
public function monaction(){
    if ($this->request->is('ajax')) {
        debug($this->request->data);
        die();
    }
}

//avec dans Produits/monaction.ctp
$.post("./produits/monaction", categories,
    function(data){
      console.log(data);
    },
    'json'   
);
Piverte
Auteur

Salut,
j'ai testé ce que tu m'as dit, j'essaie d'écrire dans ma session les data reçus mais cela ne fonctionne pas.
Dans la console : On voit bien les data partir, et on voit bien le code html revenir (le format json ne fonctionne pas, il doit y avoir une contrainte sur le paramètre data).
Par contre dès que j'effectue un traitement de mes données au niveau de l'action php, le tableau ajax reste désespérément vide.

Controller.php, action index (appelée dans le post de la requete ajax)

if ($this->request->is('ajax')) {
    $this->Session->write('ajax',$this->request->data);
    //j'ai enlevé le die(); pour que l'action cotinue mais même avec j'ai le même effet
}
debug($this->Session->read());

Lorsque je refresh la page : le session->read affiche bien le tableau 'ajax' mais il reste vide.
Cela signifierait donc que les data ne sont pas passées ?

Autre petit soucis mineur, le tableau renvoyé commence par POST puis 0 et ensuite seulement s'affichent mes catégories, y'a-t-il une option pour s'affranchir de ces deux premiers champs ?

Merci de ton aide

Assure toi d'avoir bien coché au moins une checkbox avant de rafraîchir la page. Ensuite :

if ($this->request->is('ajax')) {
    $this->Session->write('ajax',json_decode($this->request->data));
}
debug($this->Session->read());
Piverte
Auteur

Les logs de la console sont nickels mais j'obtiens toujours

'ajax' => null

dans ma session lorsque je refresh. Quelque soit le nombre de cases cochées ou décochées.
Ce sont bien les paramètres envoyées de la vue vers le controleur que l'on relit en faisant $this->request data dans le controller ?
Ce ne serait pas les paramètres renvoyées par le contrôleur vers la vue ?

En résumé ce que j'ai :

Controleur index

public function index() {
        if ($this->request->is('ajax')) {
            $this->Session->write('ajax',json_decode($this->request->data));
            debug($this->request->data);
            die();
        }
        debug($this->Session->read());

javascript

var categories = $('#categoryIndexForm input').map(function() {
          return this.value;
        }).get().join();
$.post("index", categories,
          function(data){
            console.log(data);
          },
          'json'
          );

Et ma vue :

foreach($categories as $key=>$category):
   <span class ="ajaxInput">
    <?php
    //value permet de retourner des noms plutot que des 0 et des 1
        echo $this->Form->input('nomDeLaCategory',array('type'=>'checkbox','value'=>'nomDeLaCategory'"));
    ?>
</span>
<?php endforeach; ?>

Les logs console :
POST,0,categorie1,categorie2,etc...
et la session comme je l'ai dit plus haut : 'ajax' => null

Je ne vois pas d'où vient l'erreur, tout se passe bien sauf la récupération des données côté serveur.

Merci encore pour toute l'aide que tu m'as déjà apporté Améthyste

Oops désolé, comme son nom l'indique $.post() envoie les données en POST, donc :

public function index() {
        if ($this->request->is('post')) {
            $this->Session->write('ajax',json_decode($this->request->data));
        }
        debug($this->Session->read());
}
Piverte
Auteur

oh ! j'espère que c'est ça, car je suis à court d'idées ! (je commençais à déprimer lol)
Je suis plus au boulot là, je test ça lundi et je te tiens au courant.

Juste une chose, qu'est ce qui m'empècherait de carrément enlever le if ? Le 1er chargement de la page ?

Merci en tout cas !

Piverte
Auteur

Salut,
après tests le if($this->request->is('ajax'))
fonctionne très bien, j'ai essayé d'écrire du texte dans un variable de session dans ce if et il n'y a pas de soucis.
D'ailleurs le tableau 'ajax' est bien créé mais possède une valeur 'NULL'.
A mon sens cela signifie que les data passées en ajax renvoie une valeur NULL non ?

J'ai cherché une autre façon de faire :

Avec ce code j'arrive à passer des data dans ma session.

//code jquery
$.ajax({
            type: "POST",
            url: "index",
            data:{name:"test",lol:'test'},
        });
//code coté controller
if ($this->request->is('ajax')) {
            $this->Session->write('ajax',$this->request->data);
            debug($this->request->data);
        }
debug($this->Session->read());

Cela me renvoie bien un tableau
'ajax' => array(
'name' => 'test',
'lol' => 'test2'

Néanmoins je ne sais pas <u><strong>comment récupérer les data de mon formulaire</strong></u> (c'est à dire des variables plutot que du texte dans l'exemple précédent)avec cette méthode.

Piverte
Auteur

Je viens de me rendre compte d'une chose avec la fonction $.post utilisée précédemment.
Je n'ai aucun retour de la fonction de callback, cela signifierait que la requête ajax ne se lance pas ?
Pourtant le fichier index est bien appelé lorsque je clique sur une checkbox.