jQuery - hide & show li items

b81

Nuovo Utente
5 Gen 2020
8
0
1
Ciao a tutti,
sono nuovonel forum e anche relativamente a Jquery.

Ho un problema che non riesco a risolvere e provo a chiedere il vostro aiuto.

Ho realizzato una pagina in php in csui dopo aver recuperto dati da una tabella sql costruisco due menu dropdown dipendenti. Alla selezione del primo si compilano i cmapi del secondo dinamicamente. Qui i mio codice

JavaScript:
var $select1 = $( '#select1' ),
        $select2 = $( '#select2' ),
    $options = $select2.find( 'option' );


$select1.on( 'change', function() {
    $select2.html( $options.filter( '[value="' + this.value + '"]' ) );
} ).trigger( 'change' );

L'ultima cosa che mi resta da fare è creare una lista UL LI da popolare alla selezione del secondo dropdown.

Per arrivare a questo risultato sto usando la value della option della select che viene recuperata dinamicamente e viene utilizzata per nascondere i LI che non hanno la stessa classe.

Qui il codice
JavaScript:
$( document ).ready(function() {
  $('select[name="select2"]').change(function(){
    var selected = $( "#select2 option:selected" ).val();
    $('#feature ul li').hide();
    $('#feature ul li.'+selected).show();
 });
});
Purtroppo non funziona. Sapreste aiutarmi per capire dove sto sbagliando? Ovviamente la option della select si popola dinamicamente.
qui l'html su cui sto lavorando



HTML:
        <nav class="navtop">
            <div>

                <select class="form-control" name="select1" id="select1">

                    <option value="brand">
                        Choose Brand
                    </option>

            
                    <option value="XXX">
                        XXX</option>

            
                    <option value="YYY">
                        YYY</option>

                            </select>

                <select class="form-control" name="select2" id="select2"></select>
            </div>
        </nav>

        <div id="feature" class="sidebar">

            <ul id="app">

                                    <li class="xxx">
                        <a href="#">aaa</a>
                    </li>
                                    <li class="yyy">
                        <a href="#">bbb</a>
                    </li>
                      </ul>
        </div>
 

macus_adi

Utente Attivo
5 Dic 2017
1.128
64
48
IT/SW
$( document ).ready(function() { $('select[name="select2"]').change(function(){ var selected = $( "#select2 option:selected" ).val(); $('#feature ul li').hide(); $('#feature ul li.'+selected).show(); }); });
Prova con questo!

JavaScript:
$('select[name="select2"]').change(function(){
    var selected = $( "#select2 option:selected" ).val();
console.log(selected);
dubugger
    $('ul#app li').hide();
    $('ul#app li.'+selected).show();
});
 

b81

Nuovo Utente
5 Gen 2020
8
0
1
purtroppo niente

il console.log dice selected is not defined
 

b81

Nuovo Utente
5 Gen 2020
8
0
1
pero se passo questo

JavaScript:
$( "#select2 option:selected" ).val();
sulla console mi ritorna esattamente il valore selezionato nel dropdown.

come posso risolvere? Non riesco davvero ad immaginare come.
Quando seleziono il primo dorpdown si auto selezione il secondo e si popola l'option value della seconda selection
 

marino51

Utente Attivo
28 Feb 2013
2.678
135
63
Lombardia
Quando seleziono il primo dorpdown si auto selezione il secondo e si popola l'option value della seconda selection
select2.html( options.filter( '[value="' + this.value + '"]' ) );
in realtà applichi un filtro sulle 2a select quindi "non si popola" ma deve già contenere le options che vengono "spente" con la scelta della select1

poi non capisco il passaggio alla select2, a cosa serve ?

stai attento al carattere $, in javascript con jquery ha un significato e non stai lavorando con php

quando usi dei nomi devi badare che siano identici, "XXX" é diverso da "xxx" !!

per quello che ho capito, ho "scombussolato"il tuo codice ed ora qualcosa fa, lo vedi dal risultato pubblicato,
almeno hai la traccia per sistemarlo come desideri

questo il codice,
HTML:
<script type="text/javascript" src="c:/Web_Sites/__Test/PHP/jquery.min.js"></script>
<script>
$( document ).ready(function() {
    var select1 = $( '#select1' ),
        select2 = $( '#select2' ),
        options = select2.find( 'option' );

    select1.on( 'change', function() {

        alert('select1 change ='+this.value);

        select2.html( options.filter( '[value="' + this.value + '"]' ) );

        $('#feature ul li').hide();
        $('#feature ul li.'+this.value).show();

    }).trigger( 'change' );

    $('select[name="select2"]').change(function(){

alert('select2 change ='+this.value);

//        var selected = $( "#select2 option:selected" ).val();
    });
});
</script>
<nav class="navtop">
    <div>
        <select class="form-control" name="select1" id="select1">
            <option value="vuoto">fai la tua scelta</option>
            <option value="brand">Choose Brand</option>
            <option value="XXX">XXX</option>
            <option value="YYY">YYY</option>
        </select>
        <select class="form-control" name="select2" id="select2">
            <option value="brand">Choose Brand</option>
            <option value="XXX">XXX</option>
            <option value="YYY">YYY</option>
        </select>
    </div>
</nav>

<div id="feature" class="sidebar">
    <ul id="app">
        <li class="brand">
            <a href="#">brand</a>
        </li>
        <li class="XXX">
            <a href="#">aaa</a>
        </li>
        <li class="YYY">
            <a href="#">bbb</a>
        </li>
    </ul>
</div>
1578342966614.png
1578343030324.png
 

marino51

Utente Attivo
28 Feb 2013
2.678
135
63
Lombardia
ho sostituito il "filtro" con la funzione che aggiunge la option,
é fondamentale la differenza
aggiungere significa dare la piena funzionalità, filtrare non sembra abbia la funzionalità

ora il codice si avvicina di più a quello che vorresti fare ( se capisco bene )
lo ripubblico per intero
HTML:
<script type="text/javascript" src="c:/Web_Sites/__Test/PHP/jquery.min.js"></script>
<script>
$( document ).ready(function() {
    var select1 = $( '#select1' ),
        select2 = $( '#select2' ),
        options = select2.find( 'option' );

    $('#feature ul li').hide();

    select1.on( 'change', function() {

        alert('select1 change ='+this.value);

        select2.append(
            $('<option></option>').val(this.value).html(this.value)
        );

    }).trigger( 'change' );

    select2.on( 'change', function() {

        alert('select2 change ='+this.value);

        var selected = $( "#select2 option:selected" ).val();

        alert('select2 selected ='+selected);

        $('#feature ul li').hide();
        $('#feature ul li.'+this.value).show();
    });
});
</script>
<nav class="navtop">
    <div>
        <select class="form-control" name="select1" id="select1">
            <option value="vuoto">fai la tua scelta</option>
            <option value="brand">Choose Brand</option>
            <option value="XXX">XXX</option>
            <option value="YYY">YYY</option>
        </select>
        <select class="form-control" name="select2" id="select2">
        </select>
    </div>
</nav>

<div id="feature" class="sidebar">
    <ul id="app">
        <li class="brand">
            <a href="#">brand</a>
        </li>
        <li class="XXX">
            <a href="#">aaa</a>
        </li>
        <li class="YYY">
            <a href="#">bbb</a>
        </li>
    </ul>
</div>
ps, gli alert sono comodi per vedere " l'effetto che fa "
 

b81

Nuovo Utente
5 Gen 2020
8
0
1
Anzitutto grazie del tempo e dei chiarimenti.
Devo dire che dopo aver passato un po di tempo a riflettere su quello che dicevi mi ero reso conto che il problema risiedeva nel fatto che la seconda select si popolava in automatico senza richiedere alcuna action da parte dell'utente.

Rispetto alla selezione che proponi, che mi sembra sicuramente piu elegante ed efficace, devo però capire come gestirla rispetto al modo in cui passo i valori alle select.

Come dicevo ho una pagina php che estra da db sql un array cosi fatto

Codice:
0: {0: "XXX", 1: "xxx", 2: "aaa", 3: 1, brand: "XXX", product: "xxx", app: "aaa", id_app: 1}
1: {0: "YYY", 1: "yyy", 2: "bbb", 3: 2, brand: "YYY", product: "yyy", app: "bbb", id_app: 2}
nella select uso questo codice per inserire i valori

PHP:
                <select
                class="form-control"
                name="select1"
                id="select1">
                    <option value="brand">Choose Brand</option>
                        <?php foreach($row as $item){?>
                    <option value="<?php echo strtolower($item[0]); ?>"><?php echo $item[0]; ?></option>
                        <?php    } ?>
                </select>
               <select
                class="form-control"
                name="select2"
                id="select2">
                    <option value="product">Choose Product</option>
                        <?php foreach($row as $item){?>
                    <option   value="<?php echo strtolower($item[0]); ?>"><?php echo $item[1]; ?></option>
                        <?php    } ?>
                </select>
Perdona la formattazione.
In questo modo all'azione dell'utente sulla select 1 si popolava la select2 e la lista nella sidebar.
Rivedendo il codice come da te indicato mi ritrovo gia i valori nella select2, e questo va benissimo, ma mi ritrovo anche dei valori non necessari.
La pagina dovrebbe consentire all'utente, che ha accesso ad un certo numero di brand, di selezionare quella di interesse, ritrovarsi i prodotti di riferimento nella seconda select e alla selezione del prodotto desiderato popolare la sidebar.

Per ogni utente ci possono essere da uno a piu brand
per ogni brand ci possono essere da uno a più product
per ogni product ci possono essere uno o piu app

XXX xxx etc sno attualmente degli esempi, non nomi reali, capisco possano risultare un po confusi.

In sintesi ora devo capire come filtrare i campi nella select 2 in funzione di cosa viene selezionato nella select1, almeno credo.

Ieri stavo pensando di di aggiungere una simulazione del click alla select 2, ma ora provo a capire bene il tuo codice e capire come muovermi.

Grazie mille intanto, anche se credo tornerò con alcune domande :)
 

macus_adi

Utente Attivo
5 Dic 2017
1.128
64
48
IT/SW
Per quanto riguarda la generazione delle select a cascata, eviterei l'uso di jquery senza nessun supporto....
Provando con Backbone, la situazione diventa molto più semplice, l'unica cosa è che si deve essere ben disposti a lavorare con alternative valide e aggiornate....
Piccolo estratto su una view di Backbone, si potrebbe provvedere alla creazione di una collection e ad un semplice routing app... Ma è tutt'altra storia....

Il codice risulta essere il seguente, molto più gestibile a mio avviso...

Ho bindato i dati su "obj", potrai fare modifiche semplicemente aggiungendo chiavi e valori di refs....
JavaScript:
var TestCard=Backbone.View.extend({
   el: '#wrapper',
   events:{
      "change #selezione1":"loadDue",
      "change #selezione2":"loadTre",
      "change #selezione3":"stampa"
   },
   selects:{
      uno:[
         {obj:1,text:"Seleziona 1"},
         {obj:2,text:"Seleziona 2"},
         {obj:3,text:"Seleziona 3"},
         {obj:4,text:"Seleziona 4"},
      ],
      due:[
         {obj:1,text:"Seleziona 1-1"},
         {obj:1,text:"Seleziona 1-2"},
         {obj:3,text:"Seleziona 3-3"},
         {obj:4,text:"Seleziona 4-4"},
      ],
      tre:[
         {obj:3,text:"Seleziona 3-1-3"},
         {obj:4,text:"Seleziona 4-2-4"},
         {obj:3,text:"Seleziona 3-3-3"},
         {obj:4,text:"Seleziona 4-4-4"},
      ],
   },
   initialize: function(){
      let self=this;
      let temp=$('#selezione1');
      temp.append('<option ></option>');
      _.each(self.selects.uno,function(v,k){
         temp.append('<option value="'+v.obj+'">'+v.text+'</option>');
      });

   },
   render:function(){

   },
   loadDue:function(){
      let self=this;
      let select=$('#selezione1').find(":selected").val();
      let temp=$('#selezione2');
      temp.html('');
      temp.append('<option ></option>');
      _.each(self.selects.due,function(v,k){
         if(parseInt(v.obj)===parseInt(select))temp.append('<option value="'+v.obj+'">'+v.text+'</option>');
      });
   },
   loadTre:function(){
      let self=this;
      let select=$('#selezione2').find(":selected").val();
      let temp=$('#selezione3');
      temp.html('');
      temp.append('<option ></option>');
      _.each(self.selects.due,function(v,k){
         if(parseInt(v.obj)===parseInt(select))temp.append('<option value="'+v.obj+'">'+v.text+'</option>');
      });
   },
   stampa:function(){
      $('#printing').html(JSON.stringify({uno:$('#selezione1').find(":selected").val(),
         due:$('#selezione2').find(":selected").val(),
         tre:$('#selezione3').find(":selected").val()}));
   }
});
HTML:
<div id="wrapper">
    <div>
        <select class="stm" id="selezione1"></select>
    </div>
    <div>
        <select class="stm" id="selezione2"></select>
    </div>
    <div>
        <select class="stm" id="selezione3"></select>
    </div>
    <div id="printing">

    </div>
</div>
 

b81

Nuovo Utente
5 Gen 2020
8
0
1
Ciao,

anzitutto grazie per il tempo ed i chiarimenti.
Backnone è un po sopra le mia conoscenze in questo momento. Ad ogni modo ho rivisto il modo in cui gestivo il progetto.

In considerazione del fatto che:
Per ogni utente ci possono essere da uno a piu brand
per ogni brand ci possono essere da uno a più product
per ogni product ci possono essere uno o piu app

ma che ciascuna app va inserita all'interno di un menu dedicato (ne ho 4 in tutto) ora mi sono spostato su Ajax per semplificare.
In questo momento riesco a fare tutto tranne a popolare i menu corretti. Mi sto perdendo in un biccier d'acqua e non riesco ad uscirne.

In pratica ho un HTML costruito in questo modo

HTML:
<ul class="list-unstyled components">
                <li class="s_menu">
                     <a href="#People" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">People</a>
                </li>
                    <ul  id="People" class="collapse list-unstyled"></ul>
            </ul>

            <ul class="list-unstyled components">
                <li class="s_menu">
                     <a href="#Brand" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">Brand</a>
                </li>
                    <ul  id="Brand" class="collapse list-unstyled"></ul>
            </ul>

ed ho una chiamata ajax cosi costruita
JavaScript:
$('#product').on('change', function(){
                var id_p = $(this).val();
                // alert('id_p change ='+this.value);
                if(id_p){
                    $.ajax({
                        type:'POST',
                        url:'./menu/ajaxData.php',
                        data:'id_p='+id_p,
                        dataType: "json",
                        success:function(data){
                          console.log(data)

                          var people = $.grep(data, function(m) {
                              return m.menu === 'People';});

                          console.log(people)
                          var menuitem = "";
                          $.each( people, function( i, item ) {
                            menuitem += '<li id="'+ item.id_a +'"><a href="#">' + item.app + '</a></li>';
                          });
                          $( "#People" ).html( menuitem );
                        }
                    });
                }
        })
Riesco a recuperare un array dal server e lo converto converto in json.
Ho aggiunto nella success della ajax call una funzione che filtra l'array in base ad una stringa (che corrisponde ad un dei miei menu ul) e appendo poi i li a.

Il probrlema risiede nel fatto che ho 4 menu distinti (sopra ne ho riportati solo 2) e vorrei popolarli tutti in una volta senza dover replicare 4 volte l'intero processo.

Per fare questo dovrei sicuramente sostituire People con qualcosa di dinamico e aggiungere un loop.
Non riesco davvero ad immaginare come gestire il loop. Ci ho provato in ogni modo ma è un po al di la delle mie conoscenze.

ad esempio posso recuperare gli item che andrebbero a sostituire People con il seguente codice
JavaScript:
    // menu_i= jQuery.map(data, function(n, i){
    //   return n.menu;
    // });
se hai suggerimenti sono tutto orecchi altrmenti continuerò a sbatterci la testa fino a quando non ne esco o fine a quando si romperà la testa :)
grazie in anticipo
 

macus_adi

Utente Attivo
5 Dic 2017
1.128
64
48
IT/SW
Quello scritto in backbone è facilmente intuibile e riscrivibile in jQuery style...

JavaScript:
function loadSelect(menuitem,data){
 $.each( data, function( i, item ) {
                            menuitem += '<li id="'+ item.id_a +'"><a href="#">' + item.app + '</a></li>';
   });
}

function findNewData(remoteCallObj){
return  $.ajax({
                        type:'POST',
                        url:'./menu/ajaxData.php',
                        data:'id_p='+remoteCallObj,
                        dataType: "json"
                    });
}

$(document).ready(function(){
    let select1=$('#select1');
 let select2=$('#select2');
 let select3=$('#select3');
 let select4=$('#select4');
select1.on('change',function(){
       findNewData(blablabla).then(function(response){
           loadSelect(select2,response);
       }),
});

});
Una cosa del genere, non sono sicuro sul "then" forse è success ma cambia ben poco...
 

b81

Nuovo Utente
5 Gen 2020
8
0
1
ciao scusa ma davvero non riesco ad arrivarci

considera che lo scenario è cambiato rispetto a prima

ora ho due select ed un menu composto da 4 ul

per la seconda select viene fatta una chiamata ajax in funzione del valore selezionato sulla prima select.

una volta selezionata la seconda select faccio un'altra chiamata ajax, quella indicata dal codice sopra indicato

ottengo un json cosi fatto

JSON:
0: {id_a: "3", app: "app1", id_p: "4", menu: "People"}
1: {id_a: "4", app: "app2", id_p: "4", menu: "Brand"}
il campo indicato con menu corrisponde all'ID degli ul che devo popolare

Di conseguenza devo inserire dei li con ancora all'interno dell'ul con il menu corretto

non riesco a capire come usar eil codie che hai postato in questo scenario

il codice che ti avevo postato popolava solo un ul, quello che aveva id="People"
l'unica soluzione che mi viene in mente è replicare quell'azione per ogni id di ogni ul, ripetendo quel codice 4 volte e modificando il campo dove ora c'è #People ma mi sembra poco pratico
 

macus_adi

Utente Attivo
5 Dic 2017
1.128
64
48
IT/SW
il codice che ti avevo postato popolava solo un ul, quello che aveva id="People"
l'unica soluzione che mi viene in mente è replicare quell'azione per ogni id di ogni ul, ripetendo quel codice 4 volte e modificando il campo dove ora c'è #People ma mi sembra poco pratico
Esattamente la parametrizzazione di sopra...
findNewData(blablabla).then(function(response){ loadSelect(select2,response); }),