Como adicionar ouvintes de eventos individuais usando jquery .each ()?
Tenho uma configuração simples: dois botões com valores diferentes. Quero usar a função .each () de jquery para adicionar um ouvinte de evento de clique a cada um dos botões que simplesmente registra os valores de cada botão. Mas de alguma forma, ao usar .each (), jquery sobrescreve o manipulador de cliques dos botões anteriores. Isso me deixa com duas perguntas:
- Por que é que?
- Como adicionar ouvintes de eventos individuais a uma coleção de objetos jquery?
Veja o código abaixo
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(() => { $(`button[toggle]`).each((_, button) => {
let $toggle = $(button);
type = $toggle.attr("type"); value = $toggle.attr("value");
$toggle.on("click", () => {
console.log(type, value);
});
});
});
</script>
</head>
<body>
<div>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
</div>
</body>
</html>
Respostas
O problema em seu código é porque você declarou implicitamente as variáveis type
e value
, portanto, elas estão no window
escopo. Assim, cada iteração seguinte sobrescreve os valores para que apenas os valores finais sejam vistos após o término do loop.
Para corrigir isso, defina as variáveis dentro do loop:
$(() => { $(`button[toggle]`).each((_, button) => {
let $toggle = $(button);
let type = $toggle.attr("type"); let value = $toggle.attr("value");
$toggle.on("click", () => {
console.log(type, value);
});
});
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<div>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
</div>
No entanto , você não precisa doeach()
loop de forma alguma. Você pode corrigir o problema e melhorar a qualidade do código vinculando o mesmo manipulador de eventos a todos osbutton
elementos e usando atarget
propriedade do evento que é gerada para acessar seus atributos.
Além disso, observe que adicionar seus próprios atributos não padrão, toggle
neste caso, pode causar problemas na IU e no JS. Uma abordagem melhor é usar uma classe para agrupar os elementos.
Finalmente, one
e two
não são valores válidos para o type
atributo. Em data
vez disso, use um atributo para anexar seus próprios metadados personalizados a um elemento.
Com tudo isso dito, tente isto:
jQuery($ => {
$('.toggle').on('click', e => { let $toggle = $(e.target); let type = $toggle.data("type");
let value = $toggle.prop("value");
console.log(type, value);
});
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<div>
<button class="toggle" data-type="one" value="true">One</button>
<button class="toggle" data-type="two" value="false">Two</button>
</div>
use $(this)
dentro do click callback
$(() => {
$(`button[toggle]`).each((_, button) => { $(button).on("click", function(){
type = $(this).attr("type"); value = $(this).attr("value");
console.log(type, value);
});
});
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
E também não é preciso mencionar dentro de cada callback. Você poderia ligar da maneira normal como abaixo
$(() => { $(`button[toggle]`).on("click", function(){
type = $(this).attr("type"); value = $(this).attr("value");
console.log(type, value);
});
});
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
- Porque o ouvinte se liga ao último valor de $ toggle.
- Criando e executando uma nova função conforme mostrado no snippet.
Explicado melhor nesta questão .
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(() => {
$(`button[toggle]`).each((_, button) => { let $toggle = $(button); type = $toggle.attr("type");
value = $toggle.attr("value"); $toggle.on("click", ((type, value) => {
return () => {
console.log(type, value);
};
})(type, value));
});
});
</script>
</head>
<body>
<div>
<button toggle type="one" value="true">One</button>
<button toggle type="two" value="false">Two</button>
</div>
</body>
</html>