Bonjour,
Je n'ai jamais utiliser ajax avec CakePHP et je pense que je vais devoir mettre les mains à la patte.
J'ai deux listes déroulantes. La deuxième doit afficher une liste de choix en fonction de se qui est séléctionné dans la premiere.
Pourriez-vous me mettre sur la piste si cakePHP a une fonctionnalité prévue pour cela?
Ou es-ce que je dois le faire traditonnellement?
Merci
Le truc qui me préoccupe, s'est comment interagir avec une action du controller ArticlesController, ou depuis le modele, car il faut que je passe par là pour extraire les données de ma table pour mettre a jour ma deuxième liste déroulante, en fonction du choix de la première.
Merci
J'ai pour ma part essayé de faire ceci,
Dans mon controller, j'ai ajouté cette action
function admin_refreshCategoriesAjax($id=null){
$this->loadModel('Category');
// Le list recupere la valeur des IDs et cherche un champs qui a la valeur "name"
$categories = $this->Category->find('list',array('order'=>'name ASC','conditions'=>array('shop_id'=>$id)));
#debug($categories);
return $categories;
}
Dans mon fichier default.js, j'ai ajouté ceci:
$('select#ArticleShopId').on('change',function(){
alert($(this).val());
$.get($(this).attr('href'),$(this).val(),function(data){
alert(data);
});
})
Je ne sais pas si c'est juste, mais je sait que cette partie doit etre corrigée
$(this).attr('href')
car on cherche a atteindre l'action "admin_refreshCategoriesAjax", et là est ma problématique.
Je sais pas si ca va aider mais bon ...
Je dirai que:
Tu dois envoyer la valeur de ton premier select en get (en ajax).
Ce que retourne admin_refreshCategoriesAjax() dépend de ce que tu préfères:
-> La bonne méthode serait de renvoyer du json
return json_encode( $categories );
, et de construire tes <options> en fonction de cela (regarde ici pour un exemple).
-> L'autre méthode serait de retourner une vue qui construit tes <option> (et juste tes options ... pas d'autre element, rien que la partie html correspondant a tes option ... genre elle commence par <option> .... et finie par ... </option>), et de faire un load dans ton <select>:
$( "select#ArticleShop" ).change(function(e){
$( "select#DeuxiemeSelect" ).load( "tonURLpourlAJAX&id=" + $( "select#ArticleShop" ).val() )
});
Salut,
J'ai planché depuis quelques jours là dessus. Pas tout à fait résolu mais pas loin. Si ça t’intéresse:
User, adresse, region departement ville, le tout avec de l'ajax !!!
Je peine à trouver,
J'ai essayé ceci:
$('select#ArticleShopId').on('change',function(){
//alert($(this).val());
//alert("/articles/refreshCategoriesAjax/"+$(this).val());
$.ajax({
type: "POST",
url: "./articles/admin_refreshCategoriesAjax/",
data: "id="+$(this).val(),
success: function(msg){
console.log(msg);
//msg me retourne le code HTML de la pahe entiere et non, un array selon ma fonction
}
})
})
sans succes...
C'est quoi cette URL que tu as mit dans ta fonction javascript ?
Ça ne risque pas de fonctionner comme ça.
Fais tout simplement comme ceci :
url: "<?php echo $this->Html->url(array('controller' => 'articles', 'action' => 'refreshCategoriesAjax', 'admin' => true)); ?>"
Salut! Merci pour ton aide mais malheureusement ca ne change rien..
$('select#ArticleShopId').on('change',function(){
//alert($(this).val());
//alert("/articles/refreshCategoriesAjax/"+$(this).val());
$.ajax({
type: "GET",
url: "<?php echo $this->Html->url(array('controller' => 'articles', 'action' => 'refreshCategoriesAjax', 'admin' => true)); ?>",
data: "id="+$(this).val(),
success: function(msg){
console.log(msg);
}
})
})
Ce qui est étonnant c'est que le console log retourne en debut de code qui semble etre une erreur
<h2>
<pre class="cake-error"><a href="javascript:void(0);" onclick="document.getElementById('cakeErr530b904d87e23-trace').style.display = (document.getElementById('cakeErr530b904d87e23-trace').style.display == 'none' ? '' : 'none');"><b>Notice</b> (8)</a>: Undefined index: Article <b>APP/View/Articles/admin_edit.ctp</b>, line <b>4</b>]<div id="cakeErr530b904d87e23-trace" class="cake-stack-trace" style="display: none;"><a href="javascript:void(0);" onclick="document.getElementById('cakeErr530b904d87e23-code').style.display = (document.getElementById('cakeErr530b904d87e23-code').style.display == 'none' ? '' : 'none')">Code</a> <a href="javascript:void(0);" onclick="document.getElementById('cakeErr530b904d87e23-context').style.display = (document.getElementById('cakeErr530b904d87e23-context').style.display == 'none' ? '' : 'none')">Context</a><pre id="cakeErr530b904d87e23-code" class="cake-code-dump" style="display: none;"><code><span style="color: #000000"><span style="color: #0000BB"></span><span style="color: #007700"><</span><span style="color: #0000BB">h2</span><span style="color: #007700">></span></span></code>
<code><span style="color: #000000"> <span style="color: #0000BB"><?php </span></span></code>
<span class="code-highlight"><code><span style="color: #000000"><span style="color: #0000BB"></span><span style="color: #007700">if(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">request</span><span style="color: #007700">-></span><span style="color: #0000BB">data</span><span style="color: #007700"></span><span style="color: #DD0000">'Article'</span><span style="color: #007700">]</span><span style="color: #DD0000">'category_id'</span><span style="color: #007700">]==</span><span style="color: #0000BB">0 </span><span style="color: #007700">&& </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">request</span><span style="color: #007700">-></span><span style="color: #0000BB">data</span><span style="color: #007700"></span><span style="color: #DD0000">'Article'</span><span style="color: #007700">]</span><span style="color: #DD0000">'online'</span><span style="color: #007700">]==</span><span style="color: #0000BB">0</span><span style="color: #007700">) echo </span><span style="color: #00
Nan mais pour placer du code php das du js, il faut que le js soit généré a chaque requete, et donc il doit etre dans le html entre des balises <script></script>. C'est le cas ? Parce que si ton JS est dans son fichier machin.js, ca risque pas de marcher ^^
C'est bien une erreur oui, CakePHP te dit que l'index Article n'est pas défini alors que tu l'appelles à la ligne 4 de ton fichier admin_edit.ctp
@Vallyan : Si je lui ai proposé de mettre le code PHP c'est que je me doute que c'est du script qui sera affiché sur la page et non en appel de fichier js, sinon il ne mettrait pas un lien d'URL propre à une action d'un seul controller et je ne verrais pas l'intérêt de créer un fichier JS juste pour moins de 10 lignes de javascript.
Ben oui mais pourquoi cette erreur si j'appelle une action
function admin_refreshCategoriesAjax($id = null){
$this->loadModel('Category');
// Le list recupere la valeur des IDs et cherche un champs qui a la valeur "name"
$categories = $this->Category->find('list',array('order'=>'name ASC','conditions'=>array('shop_id'=>$id)));
//return $categories;
echo json_encode($categories);
}
qui doit me retourner un tableau json ou pas, mais qui doit etre recupérer par mon code ajax, donc normalement msg.
J'ai aussi essayé de mettre ceci dans ma page admin_edit.ctp.
Ne devraos pas avoir du code Js entre mes balise <head>?
J'ai aussi ajouté Js dans mon AppController
public $helpers = array('Html','Js'=> array('Jquery'),'Text','Form','Session','Date','Cache','Subcategories','Image.Image');
Suis un peu largé..
L'erreur n'a rien à voir avec ta fonction qui utilise json, mais avec ta fonction admin_edit à mon avis.
Le script que tu nous montre, tu l'affiches avec inline false du helper html script ?
@Vallyan : Ne t'inquiètes pas, je ne te faisais pas un reproche ;)
je vous casse les pieds :o)
J'ai essayé ceci
$('select#ArticleShopId').on('change',function(){
//alert($(this).val());
//alert("/articles/refreshCategoriesAjax/"+$(this).val());
$.ajax({
type: "POST",
url: "<?php echo $this->Html->url(array('controller' => 'articles', 'action' => 'admin_refreshCategoriesAjax')); ?>",
data: {
id: $(this).val()
},
success: function(data){
alert(data);
}
});
})
Le alert devrait me retourner le tableau que j'attends, mais il me retourn ececi maintenant
<h2>Gérer, afficher, créer ou effacer vos articles.</h2>
<div class="alert alert-success">
<a href="#" class="close" title="Fermer" onclick="$(this).parent().slideUp()">x</a>
Le contenu a bien été sauvé</div><div class="row">
<div class="col-md-12">
<div class="panels panel-defaults">
<!-- Default panel contents -->
<div class="panel-body">
<a href="/sogemat/admin/articles/edit"><img src="/sogemat/img/add.png" alt="Ajouter" title="ajouter" class="btn-right" /></a>
<form action="/sogemat/admin/articles/search" class="form-inline" style="padding-left:0px;" novalidate="novalidate" role="search" id="ArticleAdminIndexForm" method="post" accept-charset="utf-8"><div style="display:none;"><input type="hid
C'est mieux, car il ne retourne plus le message d'erreur évoqué par Laktak11.
Mais ce code corespond à ma pas admin_index.ctp alors que je suis sur la page admin_edit.ctp :o)
Bonjour.
Je ne vois pas pourquoi ton code javascript te retournerait le contenu de ta vue admin_index.ctp
Et tu es bien sur d'avoir fais comme ceci sur ta page admin_edit.ctp ?
<?php $this->Html->scriptStart(array('inline' => false)); ?>
$('select#ArticleShopId').on('change',function(){
$.ajax({
type: "POST",
url: "<?php echo $this->Html->url(array('controller' => 'articles', 'action' => 'refreshCategoriesAjax', 'admin' => true)); ?>",
data: {
id: $(this).val()
},
success: function(data){
alert(data);
}
});
});
<?php $this->Html->scriptEnd(); ?>
Au passage, tu n'as pas fais le code du helper Html url que je t'avais mis, je l'ai corrigé dans ce que je viens de mettre en code.
Hello,
Ben j'ai fait exactement ce que tu m'as montré, sauf que j'ai mis ceci dans un fichier admin.js qui lui est appelé dans les <head>
echo $this->HTML->script('admin.js')
Donc , il n'y a pas ca
<?php $this->Html->scriptStart(array('inline' => false)); ?>
<?php $this->Html->scriptEnd(); ?>
$('#ArticleShopId').on('change',function(){
//alert($(this).val());
//alert("/articles/refreshCategoriesAjax/"+$(this).val());
$.ajax({
type: "POST",
url: "<?php echo $this->Html->url(array('controller' => 'articles', 'action' => 'refreshCategoriesAjax', 'admin' => true)); ?>",
data: {id:$(this).val()},
success: function(msg){
//var result = $.parseJSON(msg); //Ca marche pas
console.log(msg);
}
});
})
Dans ton categoriescontroller.php
public function admin_getCategories(){
$shop_id = $this->request->query('shop_id');
//évite de retourner toute la vue
$this->layout = 'ajax';
$this->autoRender = false;
$data = array();
if($shop_id){
$categories = $this->Categories->find('list', array(
'conditions'=>array('Categories.shop_id'=>$shop_id),
));
foreach ($categories as $k => $v) {
$data] = array(
'id'=>$k,
'value'=> $v
);
}
}
return json_encode($data);
}
et dans la vue :
<script>
$(function() {
$('#ArticleShopId').on('change',function(){
var shop_id = $(this).val();
$.get(
"./admin/categories/getCategories",
{ shop_id: shop_id},
function (data){
console.log(data);
alert('appuis sur F12');
//remplis ta 2eme select box
}
);
});
</script>
Hello, merci je vais essayé ceci. J'ai trouvé une alternative qui consite a appliqué un fadin et fadeOut sur les optgroup que ne répondent pas au menu sélectioné du premier. Mais j aimerais arrivé a ce que je voulais au départ. Donc je vais essayé ta proposition. Mille mercis
<u>Pierrot10</u>
Ben j'ai fait exactement ce que tu m'as montré, sauf que j'ai mis ceci dans un fichier admin.js qui lui est appelé dans les <head>
Ok, j'abandonne.
<u>Vallyan</u>
Nan mais pour placer du code php das du js, il faut que le js soit généré a chaque requete, et donc il doit etre dans le html entre des balises <script></script>.
C'est le cas ? Parce que si ton JS est dans son fichier machin.js, ca risque pas de marcher ^^
<u>Lartak11</u>
@Vallyan : Si je lui ai proposé de mettre le code PHP c'est que je me doute que c'est du script qui sera affiché sur la page et non en appel de fichier js, sinon il ne mettrait pas un lien d'URL propre à une action d'un seul controller et je ne verrais pas l'intérêt de créer un fichier JS juste pour moins de 10 lignes de javascript.
À croire que tu ne lis pas ou ne comprend pas ce que nous répondons à ton sujet.
@amethiste,
Je suis vraiment désolé, mais ca ne marche toujours pas :o( J'ai fais exactement ce que tu m'as proposé, soit:
Dans ma vue articles/admin_edit.ctp. La seul différence c'est que j'utilise scroptStart
<?php $this->Html->scriptStart(array('inline' => false)); ?>
$(function() {
$('#ArticleShopId').on('change',function(){
var shop_id = $(this).val();
$.get(
"./admin/categories/getCategories",
{ shop_id: shop_id},
function (data){
console.log(data);
alert('appuis sur F12');
//remplis ta 2eme select box
}
);
});
});
<?php $this->Html->scriptEnd(); ?>
alert s'affiche, mais data affiche toute ma page html, alors que j'ai besoin uniquement des catégories, soit l'extraction des catégories selon un ID
Ensuite, dans mon CategoriesController
function admin_getCategoriesAjax(){
$shop_id = $this->request->query('shop_id');
//évite de retourner toute la vue
$this->layout = 'ajax';
$this->autoRender = false;
$data = array();
if($shop_id){
//$this->loadModel('Category');
$categories = $this->Category->find('list', array(
'conditions'=>array('Category.shop_id'=>$shop_id),
));
foreach ($categories as $k => $v) {
$data] = array(
'id'=>$k,
'value'=> $v
);
}
}
return json_encode($data);
//return $data;
}
}
Si jamais, dans View/Layout/ajax.ctp, j'ai ceci
<?php
/**
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.View.Layouts
* @since CakePHP(tm) v 0.10.0.1076
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
?>
<?php echo $this->fetch('content'); ?>
Mais c'est un fichier original.
@Lartak11,
Je suis désolé, mal lu un passage, en effet.