Bonjour à tous,
Dans ma vue announce_add.ctp j'ai dans mon formulaire une liste déroulante catégories. Lorsque je clique sur l'une de ses options par exemple immobilier cela m'ouvre une autre liste déroulante sous-categories avec les options:

  • Maison,
  • Appartement,
  • Péniche
  • Divers autres appellations.
    Je voudrais que lorsque je clique par exemple sur Maison cela m'ouvre les inputs:
  • surface,
  • nombre de pièces,
  • surface du terrain.
    Si je clique sur Péniche, il n'y a pas terrain donc les inputs à afficher seront:
  • surface,
  • nombre de pièces.
    Lorsque l'on renseigne les inputs de la sous catégorie concernée, ils doivent compléter les champs de ma table options_sous_categories. Comment dois-je m'y prendre? Je sèche complétement.

Merci d'avance pour votre aide. Je ne sais pas si j'ai été assez clair!

9 réponses


christophe4427
Réponse acceptée

Chacontinue encore et encore ! (Je sors >> -])

Hum pour le Fiddle que tu viens de mettre, mouais en fait tu créé un input et tu mets la valeur du select dedans. C'est pas tout à fait ce que je t'ai indiqué ^^ Toi tu veux pas afficher un input avec un truc dedans mais juste un input.

Au pire tu vires donc cette ligne :

new_input.value = this.value;

Et hop plus de valeur dans l'input.

Après si je ne me trompe pas, faut faire une boucle pour afficher autant d'input que tu as de valeur liées.

J'ai refait un fiddle qui t'affiche un input en fonction du choix dans la liste déroulante

http://jsfiddle.net/Christoufe/ZDtvm/

mimosa21
Auteur
Réponse acceptée

Chalutations Christoufe et tous!

Hum pour le Fiddle que tu viens de mettre, mouais en fait tu créé un input et tu mets la valeur du select dedans. C'est pas tout à fait ce que je t'ai indiqué ^^ ....

Ouaip C'est parce que je suis nul en javascript et j'ai cherché une manière de faire ce que tu me disais et je suis tombé là dessus par hazard avec google et gogole n'est pas non plus mon ami quand il s'agit de te trouver un truc, il te donne des milliards de réponses SAUF CELLE QUE TU VEUX :d
Finalement j'ai fais ceci:
J'ai rajouté dans ma vue add.ctp

<div id="peniche" style="display:none;">
    <?php echo $this->element('announce_fr/peniche'); ?>
  </div>        
  <div id="maison" style="display:none;">
    <?php echo $this->element('announce_fr/maison'); ?>
  </div>
<script>    
document.getElementById('InputSubcategory_Id').onchange = function(){
    if (this.value == 27) {//péniche
        document.getElementById('peniche').style.display='block';
        document.getElementById('maison').style.display='none';
    }
    if (this.value == '24') {
        document.getElementById('peniche').style.display='none';
        document.getElementById('maison').style.display='block';
    }
}
</script>

L'élément maison.ctp

<?= $this->Form->input('Undercategory.rooms', array('id' => "nbPiece" )); ?>
<?= $this->Form->input('Undercategory.surface', array('id' => "surface" )); ?>
<?= $this->Form->input('Undercategory.ground', array('id' => "terrain" )); ?>

Voili Voilou!
Merci Christoufche

Heu alors moi je ferais avec un petit JS qui va bien.
En gros bah ton formulaire est déjà pré-construit, mais tu caches les sous catégories avec les options. (avec un petit hide()). Puis quand tu cliques sur l'une des sous catégories tu affiches les options.

J'ai fait un truc pour un système de FAQ à un moment donné, c'était bien moche (j'ai changé de système d'ailleurs) mais du coup ça remplissait bien son rôle ^^ cela te donnera sûrement une idée pour faire quelque chose de moins bourrin

jQuery(function($){
        $(".collapse").collapse(); 
        //JQUERY AFFICHAGE LISTE DEROULANTE SOUSCRIPTION
        $('#answer-faq-1').hide();
        $('#answer-faq-2').hide();
        $('#answer-faq-3').hide();

        $('.titre-cgv-1').click(function(){
            $('#answer-faq-1').show();
            $('#answer-faq-2').hide();
            $('#answer-faq-3').hide();
        });
        $('.titre-cgv-2').click(function(){
            $('#answer-faq-2').show();
            $('#answer-faq-1').hide();
            $('#answer-faq-3').hide();
        });
        $('.titre-cgv-3').click(function(){
            $('#answer-faq-3').show();
            $('#answer-faq-1').hide();
            $('#answer-faq-2').hide();
        });

});
mimosa21
Auteur

Bonjour christoufe8625 et tous!
Merci de m'avoir répondu, mais désolé, je ne vois toujours pas comment je pourrais faire. Le js et ajax sont vraiment pas mes amis.
Je montre ce que j'ai en globalité:
Mes models:

<?php // Announce model named by Announce.php
App::uses('AppModel', 'Model');
class Announce extends AppModel{
    public $name = 'Announce';
    public $belongsTo = array('Category', 'Subcategory', 'User');
}
?>
<?php
// Category model named by Category.php
App::uses('AppModel', 'Model'); 
class Category extends AppModel {
    public $name = 'Category';
    public $hasMany = array('Announce','Subcategory');
}
?>
<?php // Subcategory model named by Subcategory.php
App::uses('AppModel', 'Model');
class Subcategory extends AppModel {
    public $name = 'Subcategory';
    public $belongsTo = array('Category');
    public $hasMany = array('Announce');
}
?>

Mon controller qui englobe tout:

<?php
App::uses('AppController','Controller');
class AnnouncesController extends AppController{
    public $helpers = array('Html', 'Form', 'Session');
    public $components = array('Session');
public function add() {
    if ($this->request->is('post')) {
        $this->Announce->create();
        $this->request->data'Announce']'user_id'] = $this->Auth->user('id');
        if ($this->Announce->save($this->request->data)) {// Si la sauvegarde se passe correctement
            $this->Session->setFlash("Votre annonce a bien été enregistrée.","flash");
            return $this->redirect(array('action' => 'my'));
        }
        $this->Session->setFlash("Impossible d'ajouter votre annonce.","flash");
    }
    $categories = $this->Announce->Category->find('list', array(
        'fields' => array('Category.id','Category.name_fr'),
        'recursive' => -1,
        'order' => array('Category.name_fr ASC')
    ));
    $subcategories = $this->Announce->Subcategory->find('list', array(
        'fields' => array('Subcategory.id', 'Subcategory.name_fr')
    )); // Renvoie l'id et le name_fr
    $this->set(compact('categories', 'subcategories'));
}

Ma vue Announces/add.ctp

<?= 
    $this->Form->input('category_id', array(
        'id' =>"InputCategory_Id", 
        'label' => array('text' => "Catégorie", 'class' => 'col-lg-5 text-right')
    )); 
?>
<?= 
    $this->Form->input('subcategory_id', array(
    'id' => "InputSubcategory_Id",
        'label' => array('text' => "Sous-catégorie", 'class' => 'col-lg-5 text-right')
    ));
?>
<?php 
/* Utilisation d'ajax pour que lorsque je clique sur une catégorie dans ma liste déroulante de catégories, cela me donne bien les sous catégories liées à ma catégorie.*/
    $this->Js->get('#InputCategory_Id')->event('change',
        $this->Js->request(array(
            'controller'=>'subcategories',
            'action'=>'getByCategory'
    ), array(
            'update'=>'#InputSubcategory_Id',
        'async' => true,
        'method' => 'post',
        'dataExpression'=>true,
        'data'=> $this->Js->serializeForm(array(
        'isForm' => true,
        'inline' => true
        ))
    ))
    );
?>

Le code de mon action 'getByCategory' dans mon controler Subcategories

<!--app/Controller/SubcategoriesController.php-->
<?php
App::uses('AppController','Controller');
class SubcategoriesController extends AppController {

public function getByCategory() {
    $category_id = $this->request->data'Announce']'category_id'];
    $subcategories = $this->Subcategory->find('list', array(
        'fields' => array('Subcategory.id', 'Subcategory.name_fr'),
        'conditions' => array('Subcategory.category_id' => $category_id),
        'recursive' => -1,
        'order' => array('Subcategory.name_fr ASC')
    ));
    $this->set('subcategories',$subcategories);
    $this->layout = 'ajax';
}

La vue get_by_category.ctp

<!-- file path app/View/Subcategories/get_by_category.ctp -->
<?php
    if(!empty($subcategories)){
        foreach ($subcategories as $key => $value):
?>
            <option value="<?php echo $key; ?>"><?php echo $value; ?></option>
<?php
        endforeach;
    } else {
?>
    <option value="">No Data</option>
<?php
    }
?>

En bas de mon layout.ctp

<?php
  if (class_exists('JsHelper') && method_exists($this->Js, 'writeBuffer')) echo $this->Js->writeBuffer();
  //Writes cached scripts
?>

Mon ajax.ctp

<!-- layout/ajax.ctp -->
<?php echo $this->fetch('content'); ?>

Voilà maintenant sur le même principe que mon ajax pour Subcategories j'aimerais avoir un un model, controller et une vue pour undercategories et qui ...

Je finis à midi car je n'ai pas vu l'heure et je dois aller au boulot

Ah tiens on dirait moi quand tu dis "JS Ajax, ne sont pas mes amis" XD

En fait, (qu'on m'arrête si je dis une énorme connerie !) mais je ne suis même pas sûr que tu aies besoin d'Ajax là dedans(enfin pour le fait d'afficher les inputs). Pourquoi je dis ça ? Parce-que du coup, les inputs que tu veux afficher c'est juste de la saisie de valeur générique. Enfin tu veux que l'utilisateur puisse saisir le nombre de pièce, le nombre de m² ou autre, donc tu n'es même pas forcément obligée de lier le résultats de ces inputs au clic sur le choix.

En gros, je vais essayer d'être clair XD

Tu affiches TOUS TES INPUTS de partout, sur la page. Après, en ce qui concerne les choix, surface, pièces, tu les caches.

Un input a un ID normalement, ou s'il n'en a pas tu peux lui en mettre un, mais visiblement tu l'as :

#InputCategory_Id

Après une fois que tu as l'ID de la chose, bah tu peux cacher, ou afficher le résultat en reprenant l'exemple que j'ai mis en haut (qui est moche je pense mais bon qui fonctionne).

Exemple :

//D'abord on cache toutes les ss catégories genre SurfacePiece,SurfaceTerrain, NbPiece,etc...
        if($('input type select de ta liste deroulante == 'peniche') {
                $('#nbPiece').show();
                $('#nbSurface').show();
            } else {
                $('#nbPiece').hide();
                $('#nbSurface').hide();
            }
        if($('input type select de ta liste deroulante == 'maison') {
                $('#nbPiece').show();
                $('#nbSurface').show();
                $('#nbSurfaceTerrain').show();
            } else {
                $('#nbPiece').hide();
                $('#nbSurface').hide();
                $('#nbSurfaceTerrain').hide();
            }

Bon après je sais pas si c'est la meilleur solution, et si ce que j'ai dit est hyper méga clair mais bon ^^

mimosa21
Auteur

Merci encore une fois christoufe.
Je vais essayer. De toute façon même si ce n'est pas la meilleur solution, je ne sais pas par où commencer alors c'est pour moi la meilleure pour l'instant.
Je vais essayer!

Charoule ^^ et de rieng, :)

mimosa21
Auteur

Bon c'est un début (ça faisait une semaine que je n'avais pas écrit une ligne de code en me disant ça va marcher).
Lol ça ne marche toujours pas mais j'y crois.
Alors après avoir chercher un peu, j'ai fait ceci:
En base de données, j'ai rajouté une table undercategories

CREATE TABLE IF NOT EXISTS `undercategories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `announce_id` int(11) NOT NULL,
  `surface` int(5) NOT NULL,
  `rooms` int(2) NOT NULL,
  `bedrooms` int(2) NOT NULL,
  `type` varchar(30) NOT NULL,
  `subcategories_id` int(11) NOT NULL,
  `post_count` int(11) NOT NULL,
  PRIMARY KEY (`id`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Pour avoir accès à ma table undercategories dans mon AnnouncesController action add, j'ai rajouté cette ligne

// juste après $this->Announce->create();
    $this->loadModel('Undercategory');

Dans ma vue add.ctp

<?= $this->Form->input('Undercategory.rooms', array(
    'class' => 'col-lg-7 p0l p0r',
    'id' => "nbPiece",
    'label' => array('text' => "nombre de pièce", 'class' => 'col-lg-5 text-right')
)) ?>
<?= $this->Form->input('Undercategory.surface', array(
    'class' => 'col-lg-7 p0l p0r',
    'id' => "nbSurface",
    'label' => array('text' => "Surface habitable", 'class' => 'col-lg-5 text-right')
)); ?>
<?= $this->Form->input('Undercategory.ground', array(
    'class' => 'col-lg-7 p0l p0r',
    'id' => "nbSurfaceTerrain",
    'label' => array('text' => "Surface du terrain", 'class' => 'col-lg-5 text-right')
));?>
<script>
$(document).ready(function() {
// J'ai essayé ça mais ça ne marche pas: $("InputSubcategory_Id").click(function(){
// if($('#InputSubcategory_Id' == 'Péniche') {
// du coup j'ai trouvé ça:
    document.getElementById('subcategory_id').onchange = function(){
    if (this.value == 'Péniche') {
        $('#nbPiece').show();
        $('#nbSurface').show();
    } else {
        $('#nbPiece').hide();
        $('#nbSurface').hide();
    }
    if (this.value == 'Maison') {
            $('#nbPiece').show();
            $('#nbSurface').show();
            $('#nbSurfaceTerrain').show();
        } else {
            $('#nbPiece').hide();
            $('#nbSurface').hide();
            $('#nbSurfaceTerrain').hide();
        }
    }
}

Mes champs inputs sont visibles tout le temps
J'ai fait ce bout de code en suivant ce tuto et son fiddle qui est
Il est où le bug heiiiiing !!!! :)
Dois-je continuer en mixant ton code avec celui du fiddle ou tout simplement il manque quelque part quelque chose?
Christoufe A l'aide
Merci en tout cas et chacontinue de rouler ;)

enlève le _1 de l'input, c'était un essai mais j'arrive pas à l'enlever XD