Selecionando elemento por atributo de dados

1020

Existe um método fácil e direto para selecionar elementos com base em suas data atributos? Por exemplo, selecione todas as âncoras que possuam atributo de dados customerIDcom o valor de 22.

Eu hesito em usar relou outros atributos para armazenar essas informações, mas acho muito mais difícil selecionar um elemento com base em quais dados são armazenados nele.

Hazem Salama
fonte
2
Veja também stackoverflow.com/q/4191386/292060
goodeye
Isso foi o que me ajudou a selecionar todos os atributos de dados (independentemente do valor): $('*[data-customerID]')Você pode usá-lo com, por exemplo$('*[data-customerID]').each( function() { ... });
Kai Noack 14/01

Respostas:

1469
$('*[data-customerID="22"]');

Você deve poder omitir o *, mas, se bem me lembro, dependendo da versão do jQuery que você estiver usando, isso pode gerar resultados defeituosos.

Observe que, para compatibilidade com a API Selectors ( document.querySelector{,all}), as aspas ao redor do valor do atributo ( 22) não podem ser omitidas nesse caso .

Além disso, se você trabalha muito com atributos de dados em seus scripts jQuery, pode considerar o uso do plug-in de atributos de dados customizados HTML5 . Isso permite que você escreva um código ainda mais legível usando .dataAttr('foo')e resulta em um tamanho de arquivo menor após a minificação (comparado ao uso .attr('data-foo')).

Mathias Bynens
fonte
69
Apenas observe que .data ('foo') trabalha para obter o valor de um atributo 'data-foo' desde o jQuery 1.4.3. Além disso, desde o jQuery 1.6: .data ('fooBar') obtém o atributo 'data-foo-bar'.
James McCormack
4
@Zootius: Sim, o leia-me do plugin tem uma observação: “A partir do jQuery 1.4.3, .data()mapeia para data-*atributos personalizados por padrão, tornando esse plug-in redundante. Ainda pode ser usado para versões mais antigas do jQuery. ”
Mathias Bynens
Então, como um post do jQuery 1.4.3 seleciona um objeto pelo valor do objeto de dados? Vamos II desejar selecionar neste exemplo, qualquer objeto com dados para customerID igual a 22?
Viagem
54
Além disso, se você estiver interessado apenas na presença de atributos de dados específicos, poderá fazer o seguinte:$('[data-customerID]')
Darkside
7
Isso não funciona, se o campo de dados foi definido por jquery (using .data()), certo?
Martin R.
329

Para pessoas que pesquisam no Google e desejam regras mais gerais sobre como selecionar com atributos de dados:

$("[data-test]")selecionará qualquer elemento que possua apenas o atributo de dados (não importa o valor do atributo). Incluindo:

<div data-test=value>attributes with values</div>
<div data-test>attributes without values</div>

$('[data-test~="foo"]')selecionará qualquer elemento em que o atributo data contenha, foo mas não precise ser exato, como:

<div data-test="foo">Exact Matches</div>
<div data-test="this has the word foo">Where the Attribute merely contains "foo"</div>

$('[data-test="the_exact_value"]')selecionará qualquer elemento em que o valor exato do atributo de dados seja the_exact_value, por exemplo:

<div data-test="the_exact_value">Exact Matches</div>

mas não

<div data-test="the_exact_value foo">This won't match</div>
JTG
fonte
21
Boa. Observe que ~=corresponde a palavras separadas por espaços em branco, enquanto *=corresponde a qualquer substring.
sam
E o ^personagem?
precisa saber é o seguinte
1
@ kuba44 na verdade você também pode usar ^, como tal $('[data-test^=foo]'), neste caso, você seleciona qualquer coisa que começa com foo, como <div data-test="foo_exact_value">ou <div data-test="food">, mas não<div data-test="seafoo">
JDuarteDJ
Lista abrangente de seletores de atributos: drafts.csswg.org/selectors-3/#attribute-selectors
user1460043
142

O uso $('[data-whatever="myvalue"]')selecionará qualquer coisa com atributos html, mas no jQueries mais recente, parece que, se você usa $(...).data(...)para anexar dados, ele usa algum navegador mágico e não afeta o html, portanto, não é descoberto .findcomo indicado na resposta anterior .

Verificar (testado com 1.7.2+) (também veja violino ): (atualizado para ser mais completo)

var $container = $('<div><div id="item1"/><div id="item2"/></div>');

// add html attribute
var $item1 = $('#item1').attr('data-generated', true);

// add as data
var $item2 = $('#item2').data('generated', true);

// create item, add data attribute via jquery
var $item3 = $('<div />', {id: 'item3', data: { generated: 'true' }, text: 'Item 3' });
$container.append($item3);

// create item, "manually" add data attribute
var $item4 = $('<div id="item4" data-generated="true">Item 4</div>');
$container.append($item4);

// only returns $item1 and $item4
var $result = $container.find('[data-generated="true"]');
drzaus
fonte
1
aha - Acontece que outra pessoa aponta isso em stackoverflow.com/questions/4191386/…
drzaus:
4
e oferece uma solução com .filter aqui
drzaus
22
ele usa alguma coisinha navegador magia e não afeta o html : não existe tal coisa como mágica;) learningjquery.com/2011/09/using-jquerys-data-apis
Tom Sarduy
1
Se você estiver adicionando um atributo de dados que você precisa encontrar mais tarde, use$item.attr('data-id', 10);
Pedro Moreira
77

Não vi uma resposta JavaScript sem o jQuery. Espero que ajude alguém.

var elements = document.querySelectorAll('[data-customerID="22"]');

elements[0].innerHTML = 'it worked!';
<a data-customerID='22'>test</a>

Informações:

Sjoerd Pottuit
fonte
1
Obrigado por isso. É bom ver soluções não-jquery.
Chuck
68

Para selecionar todas as âncoras com o atributo de dados data-customerID==22, inclua o alimite do escopo da pesquisa apenas nesse tipo de elemento. Fazer pesquisas de atributos de dados em um loop grande ou em alta frequência quando houver muitos elementos na página pode causar problemas de desempenho.

$('a[data-customerID="22"]');
Travis J
fonte
27

Exemplos JS nativos

Obter NodeList de elementos

var elem = document.querySelectorAll('[data-id="container"]')

html: <div data-id="container"></div>

Obter o primeiro elemento

var firstElem = document.querySelector('[id="container"]')

html: <div id="container"></div>

Segmente uma coleção de nós que retorna um nodelist

document.getElementById('footer').querySelectorAll('[data-id]')

html:

<div class="footer">
    <div data-id="12"></div>
    <div data-id="22"></div>
</div>

Obter elementos com base em vários valores de dados (OR)

document.querySelectorAll('[data-section="12"],[data-selection="20"]')

html:

<div data-selection="20"></div>
<div data-section="12"></div>

Obter elementos com base em valores de dados combinados (AND)

document.querySelectorAll('[data-prop1="12"][data-prop2="20"]')

html:

<div data-prop1="12" data-prop2="20"></div>

Obter itens onde o valor começa com

document.querySelectorAll('[href^="https://"]')
etoxina
fonte
O seletor para "obter o primeiro elemento" está correto, mas não é consistente com os outros exemplos - acredito que estejam faltando "dados".
GuyPaddock 20/03
15

via método Jquery filter ():

http://jsfiddle.net/9n4e1agn/1/

HTML:

<button   data-id='1'>One</button>
<button   data-id='2'>Two</button>

JavaScript:

$(function() {    
    $('button').filter(function(){
        return $(this).data("id")   == 2}).css({background:'red'});  
     });
Razan Paul
fonte
Você tentou o violino? O método FIlter é apenas outra abordagem para obter a mesma coisa. Pode ser útil quando você já possui um conjunto de objetos Jquery e precisa filtrar com base no atributo de dados ou qualquer outra coisa.
Razan Paul
Minhas desculpas, @Blizzard. Eu comentei a resposta errada. Colei agora no caminho certo. #AlwaysALongDayAtWork
Peter Bishop
15

A construção assim: $('[data-XXX=111]')não está funcionando no Safari 8.0 .

Se você definir o atributo de dados desta maneira:, $('div').data('XXX', 111)ele funcionará apenas se você definir o atributo de dados diretamente no DOM, assim:$('div').attr('data-XXX', 111) .

Eu acho que é porque a equipe do jQuery otimizou o coletor de lixo para evitar vazamentos de memória e operações pesadas na reconstrução do DOM em cada atributo de alteração de dados.

Anton Danilchenko
fonte
Isso me ajudou muito - se eu usei os métodos de dados ou prop, a seleção por $ ('... [data-x = "y"]') não estava funcionando - usei attr (em vez disso, envia a alteração de atributo para o DOM). Thx
Jarda
13

Para que isso funcione no Chrome, o valor não deve ter outro par de aspas.

Funciona apenas, por exemplo, assim:

$('a[data-customerID=22]');
user55318
fonte
4
Parece estar incorreto. Pelo menos não está correto agora. Acabei de usar $ ('[data-action = "setStatus"]'). RemoveClass ('disabled'); no Chrome e funciona perfeitamente.
Peter Bishop
Eu acho que não há "" uso dentro do seletor, ele pode ser usado como$('[data-action=setStatus]').removeClass('disabled')
Animesh Singh 27/05
6

Às vezes, é desejável filtrar elementos com base no fato de eles terem itens de dados anexados a eles programaticamente (também conhecido como não através de atributos dom):

$el.filter(function(i, x) { return $(x).data('foo-bar'); }).doSomething();

O acima funciona, mas não é muito legível. Uma abordagem melhor é usar um pseudo-seletor para testar esse tipo de coisa:

$.expr[":"].hasData = $.expr.createPseudo(function (arg) {
    return function (domEl) {
        var $el = $(domEl);
        return $el.is("[" + ((arg.startsWith("data-") ? "" : "data-") + arg) + "]") || typeof ($el.data(arg)) !== "undefined";
    };
});

Agora podemos refatorar a declaração original para algo mais fluente e legível:

$el.filter(":hasData('foo-bar')").doSomething();
XDS
fonte
1
A primeira solução perde a declaração de retorno, ela deve ser: $ el.filter (função (i, x) {return $ (x) .data ('foo-bar');}). DoSomething ();
Salma Gomaa
3

Apenas para completar todas as respostas com alguns recursos do 'padrão de vida' - Até agora (na era html5), é possível fazê-lo sem uma biblioteca de terceiros:

  • JS puro / simples com querySelector (usa seletores CSS):
    • selecione o primeiro no DOM: document.querySelector('[data-answer="42"],[type="submit"]')
    • selecione tudo no DOM: document.querySelectorAll('[data-answer="42"],[type="submit"]')
  • CSS puro / simples
    • algumas tags específicas: [data-answer="42"],[type="submit"]
    • todas as tags com um atributo específico: [data-answer]ouinput[type]
Sven
fonte