Bonjour tout le monde,
je viens de développer une application avec le framework CakePHP ,
et je veux intégrer du ajax en utilisant un filtre de recherche.
voici la vue fronts/home.ctp :

<div class="container" style="max-width:960px;height:100%">
    <div class="collapse navbar-collapse">
        <div>
            <div style="float:left; " class="slideshow" id="flavor_3"></div>
        </div>
    </div>
</div>
<div class="container" style="max-width:960px;height:100%">
    <div id="filters" class="collapse navbar-collapse" style="background-color:#9B9B9B; margin:10px; border-bottom: 1px solid #8D8D8D; border-radius: 5px 5px 5px 5px;">
        <h4>Personnalisez votre contenu :</h4>

            <?php
            echo Configure::version();
            echo $this->Form->create('Deal', array(
                'url' => array('controller' => 'fronts', 'action' => 'test'))
            );
            ?>
            <?php
            echo $this->Form->input('city_id', array(
                'type' => 'select',
                'label' => '',
                'id' => 'city-id',
                'empty' => 'Ou ?',
            ));
            ?>
            <?php
            echo $this->Form->input('category_id', array(
                'type' => 'select',
                'label' => '',
                'id' => 'category-id',
                'empty' => 'Quoi ?',
            ));
            ?>

            <?php
            echo $this->Form->input('partner_id', array(
                'type' => 'select',
                'label' => '',
                'id' => 'partner-id',
                'empty' => 'Qui ?',
            ));
            ?>

            <?php echo $this->Form->submit('Valider'); ?>
            <?php echo $this->Form->end(); ?>   

    </div>
    <div id="product-container">
        <div id="filters"></div>
        <div class="row show-grid" id="container1">
            c'est ici ou se place le resultat via ajax
        </div>
    </div>
</div><!-- /.container -->

<script type="text/javascript">
    $(document).ready(function() {
        var Ville = '';
        var Category = '';
        var Partner = '';
        var POST;
        $("#city-id").bind('change', function(e) {
            e.preventDefault();
            Ville = $(this).find("option:selected").attr('value');
            // $("#product-container").slideUp('slow');
            $("#product-container #filters").find(".city").remove();
            if ($(this).find("option:selected").text() !== "Ou ?") {
                $("#product-container #filters").append("<span class='filter-item city'>" + $(this).find("option:selected").text() + "</span>");
            }
            go();
        })

        $("#partner-id").bind('change', function(e) {
            e.preventDefault();
            Partner = $(this).find("option:selected").attr('value');
            // $("#product-container").slideUp('slow');
            $("#product-container #filters").find(".partner").remove();
            if ($(this).find("option:selected").text() !== "Qui ?") {
                $("#product-container #filters").append("<span class='filter-item partner'>" + $(this).find("option:selected").text() + "</span>");
            }
            go();
        })
        $("#category-id").bind('change', function(e) {
            e.preventDefault();
            Category = $(this).find("option:selected").attr('value');
            //$("#product-container").slideUp('slow');
            $("#product-container #filters").find(".marque").remove();

            if ($(this).find("option:selected").text() !== "Quoi ?") {
                $("#product-container #filters").append("<span class='filter-item category'>" + $(this).find("option:selected").text() + "</span>");
            }
            go();
        })
        function go() {
            POST = {Deal: {city_id: Ville, category_id: Category, partner_id: Partner}};
            $.ajax({
                type: 'POST',
                url: 'fronts/test',
                data: POST,
                success: function(data) {
                    $("#product-container ").slideDown('slow');
                    $("#product-container #container1").html(data);
                },
                error: function(data) {
                    alert('An unexpected error has occurred!');
                    $("#product-container ").slideDown('slow');
                    $("#product-container #container1").html('<b>errooor</b>');
                }
            });
        }
    });
</script>

j'ai fais une fonction de test dans le contrôleur FrontsController juste pour tester ,

public function test(){

die('Contenu Ajax');
}

public function test(){

        die('Contenu Ajax');
    }

le problème c'est dans le java script :

$.ajax({
                type: 'POST',
                url: 'fronts/test',
                data: POST,
                success: function(data) {
                    $("#product-container ").slideDown('slow');
                    $("#product-container #container1").html(data);
                },
                error: function(data) {
                    alert('An unexpected error has occurred!');
                    $("#product-container ").slideDown('slow');
                    $("#product-container #container1").html('<b>errooor</b>');
                }
            });

je reçois toujours le message d'alerte 'An unexpected error has occurred!'
donc je pense que y a un problème au niveau du data.

Aidez moi de trouver une solution !
Et merci ..

4 réponses


Xeta
Réponse acceptée

Hello,
Normal car tu met un die() dans l'action de ton controller, et donc le JS n'arrive pas à récupérer la réponse puisque sa stop l'application.
Je vais te donner plusieurs conseille pour améliorer ton code :

  • J'ai remarqué que dans chaque input, tu met " label => ''", plutôt que de répéter ça, met le directement dans la création de la form et sa va s'appliquer à tous tes inputs :

    <?= $this->Form->create('Deal', array(
    'url' => array('controller' => 'fronts', 'action' => 'test'))
    'inputDefaults' => array(
    'label'=>false,
    //'div' => false //Ça, c'est si tu veux désactiver les div aussi.
    )
    ); ?>

  • Pour gérer les URLs des requêtes AJAX (qui peuvent être amenées à changer dans le temps), je te conseille de mettre un input hidden avec comme value, la route de la requête AJAX et tu la récupère en JS :

    <?= $this->Form->input(null, array(
    'type' => 'hidden',
    'id' => 'route-ajax',
    'data-url' => Router::url(array('controller' => 'fronts', 'action' => 'test'))
    )); ?>
    $.ajax({
    type: 'POST',
    url: $('#route-ajax').attr('data-url'),
    data: POST,
    ...
    });

Comme ça, si pour X raison tu décide de changer le nom de l'action par exemple où mettre un prefix etc, tu as juste à éditer soit ton fichier routes.php soit ta vue sans toucher au JS. Il y a d'autre méthode aussi, comme par exemple récupérer l'URL de la form via :

//#ControllerActionForm (De mémoire)
$('#FrontsTestForm').attr('action')
  • Plutôt que d'écrire <?php echo qui peut vite devenir chiant à la longue, écris <?=. (Comme dans mes exemples)

  • Et pour tester ta vue (pour être sûr que le JS fonctionne), renvoie juste un bout de code html :

    public function test(){
    //On verifie si c'est bien une requête AJAX, sinon on lui renvoie une erreur 404
    if($this->request->is('ajax'))
    {
    $testMessage = "Hello world";
    $this->set(compact('testMessage'));
    } else {

        throw new NotFoundException();
    }

    }
    //Puis, dans ta vue app/View/Fronts/test.ctp :
    <?php if(isset($testMessage)): ?>
    <?= h($testMessage) ?>
    <?php endif; ?>

Et normalement, le JS devrais récupérer ce message et te l'afficher.

lynxfg
Auteur

Merci Pour votre aide; j'ai mis la function die('message') juste pour le test, donc le message de die() devrai être afficher dans la div

container1,

mon problème c'est dans cette URL (front/test) ne l intercepte pas, je reçois toujours l'alerte d'erreur

Ba je t'ais expliqué des alternatives pour avoir des URLs dynamiques, à toi de mettre ça en place et de tester.
Et quand au die, non sa ne fonctionne pas comme ça avec de l'AJAX. Si tu stop l'application il prend ça comme une erreur, et donc exécute le callback error. En php seul oui, mais pas en AJAX.
Et quand tu fait de l'AJAX, surtout au début, prend l'habitude de regarder dans la console de Chrome ou Mozilla pour voir se qui se passe. TOUT est dit dedans, dans l'onglet Network, tu as l'url de la requête avec le statut de celle-ci, et si tu clique dessus, tu auras d'autres onglet, en l’occurrence Headers, où tu peux voir les données qui sont envoyé + d'autres infos utiles, et aussi un onglet Response, qui est la réponse renvoyé par CakePHP, et donc si tu as une erreur du côté de CakePHP, tu la verras dans cet onglet.(Fort utile quand on fait de l'AJAX car on voie pas trop ce qui se passe dans CakePHP)

Coucou,
Je rajouterai qu'en générant des flux json\xml depuis ton controlleur, tu auras plus de facilité à gérer ton content en js
Fin moi perso en tout cas que je gère des cas en ajax dans mon appli, je génére automatiquement des flux json ^^

Si tu veux retourner vraiment du html, il ne faut pas oublié de créer ta vue, sinon ca ne passera pas non plus.
Et dans le cas ou tu modifie un formulaire dynamiquement en ajax et que ta le composant security d'activer n'oublie pas la gestion des tokens ou le unlockActions ou unlockedFields sinon c'est black hole assuré