2015-07-22 17 views
6

Ho riscontrato un caso strano in cui, per quanto ne so, due cose che dovrebbero comportarsi allo stesso modo si comportano in modo diverso.Il menu di selezione aggiunto dinamicamente con la prima opzione disabilitata seleziona automaticamente la seconda opzione

Se sono presenti due menu di selezione in una pagina, un menu statico codificato in codice HTML e uno aggiunto al corpo in fase di esecuzione con JQuery. Quindi disabilito la prima opzione in entrambi i menu di selezione. Quando vengono visualizzati entrambi i menu hanno disattivato le loro prime opzioni come previsto, tuttavia il menu aggiunto in modo dinamico ha automaticamente impostato il valore sulla seconda opzione mentre il menu statico ha ancora il primo selezionato.

http://jsfiddle.net/hm3xgkLg/1/

HTML:

<select class="dropMenu"> 
    <option value="1">First</option> 
    <option value="2">Second</option> 
    <option value="3">Third</option> 
    <option value="4">fourth</option> 
</select> 

Javascript:

var arr = [ 
    {val : 1, text: 'One'}, 
    {val : 2, text: 'Two'}, 
    {val : 3, text: 'Three'}, 
    {val : 4, text: 'Four'} 
]; 

var sel = $('<select class="dropMenu">').appendTo('body'); 
$(arr).each(function() { 
    sel.append($("<option>").attr('value',this.val).text(this.text)); 
}); 
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled'); 

Perché questi due apparentemente identiche selezionare i menu comportano in modo diverso? Vorrei che entrambi si comportassero come il menu statico (mantenere selezionato il primo valore) è possibile?

Va anche notato che ho provato a racchiudere la funzione di disabilitazione in $ (document) .ready per escludere un problema del menu non ancora eseguito, ma non ci sono stati cambiamenti. Ho anche provato ad avere due classi distinte con due chiamate separate per disabilitare le opzioni per assicurarmi che non si scontrasse in qualche modo senza alcun cambiamento.

+0

L'approccio nella risposta accettata qui sembra funzionare anche http://stackoverflow.com/questions/14227611/jquery-force-display- di-modified-dom ma non capisco del tutto perché. http://jsfiddle.net/hm3xgkLg/4/ – heisenberg

+0

prova a impostare l'opzione '$ ('. dropMenu: nth-child (1)'). attr ('disabled', 'disabled');' in setInterval –

risposta

5

Perché questi due apparentemente identiche selezionare i menu che si comportano in modo diverso

Questo perché il primo select faceva già parte del documento ed è stato analizzato. :

Lo stato iniziale ha la prima opzione selezionata ..

e quindi la prima opzione era preselezionata. Successivamente, disabilitando un'opzione, la selezione non viene modificata.

Esempio 1: Si può vedere che la prima select ha disabled attributo già applicata alla prima opzione nel markup. La seconda opzione viene preselezionata, rispetto al secondo select.

<select class="dropMenu"> 
 
    <option value="1" disabled>First</option> 
 
    <option value="2">Second</option> 
 
    <option value="3">Third</option> 
 
    <option value="4">fourth</option> 
 
</select> 
 
<select class="dropMenu"> 
 
    <option value="1">First</option> 
 
    <option value="2">Second</option> 
 
    <option value="3">Third</option> 
 
    <option value="4">fourth</option> 
 
</select>

Nel tuo caso di aggiungere dinamicamente un select utilizzando Javascript, il secondo select è stato creato e aggiunto al body immediatamente. Quando questo è diventato la parte del DOM, non ci sono opzioni e quindi nessuna pre-selezione possibile. Più tardi, quando aggiungi delle opzioni e poi disabiliti una delle opzioni, sembra che venga eseguita troppo velocemente e quando viene caricata la prima opzione è già disabilitata e la seconda viene preselezionata.

Esempio 2: Non aggiungere il select immediatamente al body. Aggiungilo dopo aver popolato lo options. Questa volta, il primo option verrà preselezionato nonostante si modifichi l'attributo disabled in seguito.

var arr = [ 
 
    {val : 1, text: 'One'}, 
 
    {val : 2, text: 'Two'}, 
 
    {val : 3, text: 'Three'}, 
 
    {val : 4, text: 'Four'} 
 
]; 
 

 
var sel = $('<select class="dropMenu">'); 
 
$(arr).each(function() { 
 
    sel.append($("<option>").attr('value', this.val).text(this.text)); 
 
}); 
 

 
sel.appendTo('body'); /* <--- append here */ 
 

 
$('.dropMenu option:nth-child(1)').prop('disabled', true);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<select class="dropMenu"> 
 
    <option value="1">First</option> 
 
    <option value="2">Second</option> 
 
    <option value="3">Third</option> 
 
    <option value="4">fourth</option> 
 
</select>

Esempio 3: Aggiungere un ritardo prima di disable un option. Questo ti darà il comportamento desiderato di ottenere il primo option preselezionato perché avrà abbastanza tempo.

var arr = [ 
 
    {val : 1, text: 'One'}, 
 
    {val : 2, text: 'Two'}, 
 
    {val : 3, text: 'Three'}, 
 
    {val : 4, text: 'Four'} 
 
]; 
 

 
var sel = $('<select class="dropMenu">').appendTo('body'); 
 
$(arr).each(function() { 
 
    sel.append($("<option>").attr('value', this.val).text(this.text)); 
 
}); 
 

 
setTimeout(disable, 1000); /* <--- give some delay here */ 
 

 
function disable() { 
 
    $('.dropMenu option:nth-child(1)').prop('disabled', true); 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<select class="dropMenu"> 
 
    <option value="1">First</option> 
 
    <option value="2">Second</option> 
 
    <option value="3">Third</option> 
 
    <option value="4">fourth</option> 
 
</select>

Esempio 4: È anche possibile selezionare uno option esplicitamente prima di loro disattivazione.

var arr = [ 
 
    {val : 1, text: 'One'}, 
 
    {val : 2, text: 'Two'}, 
 
    {val : 3, text: 'Three'}, 
 
    {val : 4, text: 'Four'} 
 
]; 
 

 
var sel = $('<select class="dropMenu">').appendTo('body'); 
 
$(arr).each(function() { 
 
    sel.append($("<option>").attr('value', this.val).text(this.text)); 
 
}); 
 

 
$('.dropMenu option:nth-child(1)').prop('selected', true); /* <-- select explicitly */ 
 
$('.dropMenu option:nth-child(1)').prop('disabled', true);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<select class="dropMenu"> 
 
    <option value="1">First</option> 
 
    <option value="2">Second</option> 
 
    <option value="3">Third</option> 
 
    <option value="4">fourth</option> 
 
</select>

+1

QUESTO risolve il mistero! Splendida! – lucasnadalutti

0

Bene per impostazione predefinita se hai dato l'opzione selected per la prima opzione della dinamica dropdown allora sarebbe stato fatto per voi:

Basta vedere questo DEMO:

$(arr).each(function(key,value) { 
    if(key==0) 
     sel.append($("<option>").attr('value',this.val).text(this.text).attr('selected',true)); 
    else 
     sel.append($("<option>").attr('value',this.val).text(this.text)); 
}); 

Ora perché questo succede?

Per statico select, l'elemento è già presente in DOM e poi si aggiunge disabled per primo option utilizzando jquery e di default prima option saranno tenuti come selected già.

Ora, per dinamica select dal momento che si sta aggiungendo che dynamically può essere che non sta prendendo in considerazione per la prima selectoption di default, che è disabilitato !!

Anche io lo sento come un comportamento strano, ma a volte abbiamo bisogno di prenderci cura di queste cose seguendo sentieri ed errori.

+1

That's la soluzione di sicuro, ma ancora non spiega il comportamento curioso che l'OP ha trovato. – lucasnadalutti

+0

@lucasnadalutti Beh, ho cercato di spiegare al meglio delle mie conoscenze e questo è dal mio punto di vista o posso dire che è quello che posso estendere le mie conoscenze! Sempre gradito se qualcuno ha una conoscenza migliore su questo .. :) –

+1

Questo funziona per lo scenario dato, ma in realtà non sto usando una semplice matrice per popolare il menu a discesa, sono i dati JSON estratti dal server e aggiunti a un Knockout .js template come array quindi non posso usare questa soluzione nel mio caso. L'ho semplicemente semplificato per rendere il punto come lo stesso risultato.Se non riesco a trovare una soluzione utilizzabile, accetterò il tuo perché soddisfa il problema indicato. – DasBeasto

0

Basta selezionare manualmente la prima opzione nel menu dinamicamente aggiunto:

$('.dropMenu option:nth-child(1)') 
     .attr('disabled', 'disabled') 
     .attr('selected', 'selected'); 

jsfiddle qui (ho preso in prestito la vostra: P): https://jsfiddle.net/z0dzk5nL/1/

EDIT A qu aggiornamento ick. Here puoi trovare le specifiche per l'elemento "seleziona".Ho citato la parte che risponde alla tua domanda:

Se i nodi sono inseriti o nodi vengono rimossi causando la lista di opzioni di guadagnare o perdere uno o più elementi di opzione, o se un elemento un'opzione nella lista di opzioni chiede un reset, quindi, se attributo multiple dell'elemento di selezione è assente, il programma utente deve eseguire il primo serie applicabile di scalini dal seguente elenco:

Se dimensione di visualizzazione dell'elemento selezionato è 1, e nessun elemento opzione in l'elenco di opzioni dell'elemento selezionato ha la sua selectnessità impostata su true Imposta la selezione del primo elemento di opzione nell'elenco delle opzioni in albero che non è disabilitato, se presente, su true.

Se due o più elementi di opzione in lista dell'elemento selezionato di opzioni hanno la loro selectedness impostata su true Impostare la selectedness di tutti, ma l'ultimo elemento di opzione con la sua selectedness impostata su true nella lista di opzioni al fine albero a falso.

Ed ecco il violino per dimostrare che se si pre-selezionare l'opzione quando si aggiunge, è possibile che disabilitare senza perdere la selezione (io ho usato un ciclo for al posto del "ciascun" Funz esattamente per dimostrare che) :

jsfiddle.net/xnvbevhm/

(mi dispiace non posso postare più di due link, come io non ho abbastanza reputazione: P)

0

in alternativa a fissando il primo attributo come selezionato , usare setTimeout con un tempo minimo (cioè 1) sembra che le cose si comportino come previsto. Sto ancora ricercando la ragione di questo, però.

setTimeout(function() { 
    $('.dropMenu option:nth-child(1)').attr('disabled', 'disabled'); 
}, 1); 

Updated fiddle.

+0

può anche usare 0 per il timeout ... http://jsfiddle.net/hm3xgkLg/4/ – heisenberg

1

cerca di impostare il vostro $('.dropMenu option:nth-child(1)').attr('disabled', 'disabled'); in setInterval, perché si sta creando a discesa dinamico in modo che ci vorrà del tempo per eseguire e creare nel frattempo si disabilita discesa elemento jQuery sta per eseguire. così che il problema arriva.

Checkout frammento di codice

var arr = [ 
 
    {val : 1, text: 'One'}, 
 
    {val : 2, text: 'Two'}, 
 
    {val : 3, text: 'Three'}, 
 
    {val : 4, text: 'Four'} 
 
]; 
 

 
var sel = $('<select class="dropMenu">').appendTo('body'); 
 
$(arr).each(function() { 
 
    sel.append($("<option>").attr('value',this.val).text(this.text)); 
 
}); 
 

 

 
setTimeout(function() { 
 
    $('.dropMenu option:nth-child(1)').attr('disabled', 'disabled'); 
 
}, 1);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<select class="dropMenu"> 
 
    <option value="1">First</option> 
 
    <option value="2">Second</option> 
 
    <option value="3">Third</option> 
 
    <option value="4">fourth</option> 
 
</select>

Problemi correlati