Como obter todos os valores selecionados de <select multiple = multiple>?

115

Pareceu estranho não consegui encontrar este já perguntado, mas aqui vai!

Eu tenho um html da seguinte maneira:

<select id="select-meal-type" multiple="multiple">
    <option value="1">Breakfast</option>
    <option value="2">Lunch</option>
    <option value="3">Dinner</option>
    <option value="4">Snacks</option>
    <option value="5">Dessert</option>
</select>

Como obtenho todos os valores (uma matriz?) Que o usuário selecionou em javascript?

Por exemplo, se o usuário selecionou Almoço e Lanches, quero uma matriz de {2, 4}.

Parece que deveria ser uma tarefa muito simples, mas não consigo fazer isso.

Obrigado.

Kyle
fonte

Respostas:

105

A maneira usual:

var values = $('#select-meal-type').val();

Dos documentos :

No caso de <select multiple="multiple">elementos, o .val()método retorna um array contendo cada opção selecionada;

Felix Kling
fonte
10
@augurone: Eu afirmo que é?
Felix Kling
9
@FelixKling, você enganou alguém que pode imediatamente incluir o jQuery lib inteiro apenas para isso, antes de perceber que não deveria, a menos que realmente precise.
Aamir Afridi
32
@AamirAfridi: a questão está marcada com jQuery. Marcar uma pergunta com uma biblioteca geralmente significa que o op usa essa biblioteca e que as respostas que fazem uso da biblioteca são bem-vindas. Eu também sugeriria uma porta alternativa para o jQuery hoje? Talvez. Mas esta pergunta tem mais de 3 anos. Veja também o comentário do OP sobre a outra resposta: stackoverflow.com/questions/11821261/…
Felix Kling
12
Você está certo. Faz sentido se a pergunta estiver marcada com jQuery 😐
Aamir Afridi
148

A menos que uma pergunta seja feita por JQuery, a pergunta deve ser respondida primeiro em javascript padrão, pois muitas pessoas não usam JQuery em seus sites.

De RobG Como obter todos os valores selecionados de uma caixa de seleção múltipla usando JavaScript? :

  function getSelectValues(select) {
  var result = [];
  var options = select && select.options;
  var opt;

  for (var i=0, iLen=options.length; i<iLen; i++) {
    opt = options[i];

    if (opt.selected) {
      result.push(opt.value || opt.text);
    }
  }
  return result;
}
Ivoelk
fonte
24
Está marcado com jquery.
Kyle
1
ha, não vi isso: / ainda +1
mw_21 01 de
6
Sobre o quê selectedOptions? Não é cross-browser suficiente? Array.prototype.map.call(el.selectedOptions, function(x){ return x.value })
tenbits
Observe que quando não há nenhum valueatributo, então opt.value= opt.text.
thdoan
1
Finalmente! Baunilha ... meu sabor favorito
papiro
46

Na verdade, descobri que a maneira melhor, mais sucinta, mais rápida e mais compatível de usar JavaScript puro (presumindo que você não precise dar suporte total ao IE lte 8) é a seguinte:

var values = Array.prototype.slice.call(document.querySelectorAll('#select-meal-type option:checked'),0).map(function(v,i,a) { 
    return v.value; 
});

ATUALIZAÇÃO (14/02/2017):

Uma forma ainda mais sucinta usando ES6 / ES2015 (para os navegadores que o suportam):

const selected = document.querySelectorAll('#select-meal-type option:checked');
const values = Array.from(selected).map(el => el.value);
KyleFarris
fonte
7
Como alternativa, se você tiver o elemento:Array.from(element.querySelectorAll("option:checked"),e=>e.value);
Someguynamedpie
1
Apenas para sua informação, é mais rápido usar a coleção selectedOptions / options do que usar querySelectorAll.
Adam Leggett
4
Obrigado @AdamLeggett. Para referência para aqueles que não sabem, que mudaria make @ código de Someguynamedpie acima para: Array.from(element.selectedOptions).map(v=>v.value);.
KyleFarris
Sim, mas veja minha resposta abaixo - não funciona no IE e tem um comportamento estranho em algumas versões mais antigas do Chrome e do Firefox. Se você não se preocupa com o desempenho, querySelectorAll ou filtering element.options dão conta do recado. Além disso, você pode fazer [] .map.call () em vez de usar Array.from (), não sei que impacto isso teria no desempenho, mas certamente não seria negativo.
Adam Leggett
usado checked Isso funcionou para mim, em um menu suspenso de seleção múltipla, mas deve funcionar para todos os menus suspensos também$(".multiple_select > option:checked").each(function(){ console.log(this.value) });
Joviano Dias
15

Se você quiser seguir o caminho moderno, pode fazer o seguinte:

const selectedOpts = [...field.options].filter((x) => x.selected);

O ...operador mapeia iterable ( HTMLOptionsCollection) para a matriz.

Se você está interessado apenas nos valores, pode adicionar uma map()chamada:

const selectedValues = [...field.options]
                     .filter((x) => x.selected)
                     .map((x)=>x.value);
Tomáš Zato - Reintegrar Monica
fonte
Essa resposta merece muito mais crédito. Solução perfeita, obrigado!
Silver Ringvee
10

Primeiro, use Array.frompara converter o HTMLCollectionobjeto em uma matriz.

let selectElement = document.getElementById('categorySelect')
let selectedValues = Array.from(selectElement.selectedOptions)
        .map(option => option.value) // make sure you know what '.map' does

// you could also do: selectElement.options
Hassan
fonte
9

$('#select-meal-type :selected') irá conter uma matriz de todos os itens selecionados.

$('#select-meal-type option:selected').each(function() {
    alert($(this).val());
});

John Conde
fonte
6

Atualização de outubro de 2019

O seguinte deve funcionar "autônomo" em todos os navegadores modernos sem quaisquer dependências ou transpilação.

<!-- display a pop-up with the selected values from the <select> element -->

<script>
 const showSelectedOptions = options => alert(
   [...options].filter(o => o.selected).map(o => o.value)
 )
</script>

<select multiple onchange="showSelectedOptions(this.options)">
  <option value='1'>one</option>
  <option value='2'>two</option>
  <option value='3'>three</option>
  <option value='4'>four</option>
</select>
Fergie
fonte
4

Experimente isto:

$('#select-meal-type').change(function(){
    var arr = $(this).val()
});

Demo

$('#select-meal-type').change(function(){
  var arr = $(this).val();
  console.log(arr)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="select-meal-type" multiple="multiple">
  <option value="1">Breakfast</option>
  <option value="2">Lunch</option>
  <option value="3">Dinner</option>
  <option value="4">Snacks</option>
  <option value="5">Dessert</option>
</select>

rabeca

Indefinido
fonte
3

se quiser como expressou com intervalos após cada valor;

$('#select-meal-type').change(function(){
    var meals = $(this).val();
    var selectedmeals = meals.join(", "); // there is a break after comma

    alert (selectedmeals); // just for testing what will be printed
})
Ewroman
fonte
2

Se você precisar responder às mudanças, pode tentar o seguinte:

document.getElementById('select-meal-type').addEventListener('change', function(e) {
    let values = [].slice.call(e.target.selectedOptions).map(a => a.value));
})

O [].slice.call(e.target.selectedOptions)é necessário porque e.target.selectedOptionsretorna um HTMLCollection, não um Array. Essa chamada o converte em Arraypara que possamos então aplicar a mapfunção, que extrai os valores.

adlr0
fonte
1
Infelizmente, isso não funcionará em todos os lugares, mas o IE11 não tem o campo selectedOptions. No entanto, o seguinte funciona:Array.prototype.slice.call(field.querySelectorAll(':checked'))
JamesDev
0

Algo como o seguinte seria minha escolha:

let selectElement = document.getElementById('categorySelect');
let selectedOptions = selectedElement.selectedOptions || [].filter.call(selectedElement.options, option => option.selected);
let selectedValues = [].map.call(selectedOptions, option => option.value);

É curto, é rápido em navegadores modernos e não nos importamos se é rápido ou não em navegadores de 1% do mercado.

Observe que o selectedOptions tem um comportamento instável em alguns navegadores há cerca de 5 anos, então um user agent sniff não está totalmente fora de linha aqui.

Adam Leggett
fonte
0

Você pode usar selectedOptions

var selectedValues = Array.from(document.getElementById('select-meal-type').selectedOptions).map(el=>el.value);
console.log(selectedValues);
<select id="select-meal-type" multiple="multiple">
    <option value="1">Breakfast</option>
    <option value="2" selected>Lunch</option>
    <option value="3">Dinner</option>
    <option value="4" selected>Snacks</option>
    <option value="5">Dessert</option>
</select>

Tang Chanrith
fonte
-1

Funciona em qualquer lugar sem jquery:

var getSelectValues = function (select) {
    var ret = [];

    // fast but not universally supported
    if (select.selectedOptions != undefined) {
        for (var i=0; i < select.selectedOptions.length; i++) {
            ret.push(select.selectedOptions[i].value);
        }

    // compatible, but can be painfully slow
    } else {
        for (var i=0; i < select.options.length; i++) {
            if (select.options[i].selected) {
                ret.push(select.options[i].value);
            }
        }
    }
    return ret;
};
Paul Cuddihy
fonte
selectedOptiongsnão é compatível com o IE
Dustin Poissant