Seleccionar elemento por atributo de datos

1020

¿Existe un método sencillo y directo para seleccionar elementos en función de sus dataatributos? Por ejemplo, seleccione todos los anclajes que tengan un atributo de datos denominado customerIDque tenga el valor de 22.

Dudo un poco en usar relu otros atributos para almacenar dicha información, pero me resulta mucho más difícil seleccionar un elemento en función de los datos almacenados en él.

Hazem Salama
fuente
2
Ver también stackoverflow.com/q/4191386/292060
goodeye
Eso es lo que me ayudó a seleccionar todos los atributos de datos (independientemente del valor): $('*[data-customerID]')puede usarlo con, por ejemplo$('*[data-customerID]').each( function() { ... });
Kai Noack el

Respuestas:

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

Debería poder omitir el *, pero si recuerdo correctamente, dependiendo de la versión de jQuery que esté utilizando, esto podría dar resultados defectuosos.

Tenga en cuenta que, por compatibilidad con la API de selectores ( document.querySelector{,all}), las comillas alrededor del valor del atributo ( 22) no se pueden omitir en este caso .

Además, si trabaja mucho con atributos de datos en sus scripts jQuery, es posible que desee considerar el uso del complemento de atributos de datos personalizados HTML5 . Esto le permite escribir código aún más legible mediante el uso .dataAttr('foo')y da como resultado un tamaño de archivo más pequeño después de la minificación (en comparación con el uso .attr('data-foo')).

Mathias Bynens
fuente
69
Solo una nota de que .data ('foo') funciona para obtener el valor de un atributo 'data-foo' desde jQuery 1.4.3. Además, desde jQuery 1.6: .data ('fooBar') obtiene el atributo 'data-foo-bar'.
James McCormack
44
@Zootius: Sí, el archivo Léame del complemento tiene una nota al respecto: “A partir de jQuery 1.4.3, los .data()mapas se asignan a los data-*atributos personalizados de forma predeterminada, lo que hace que este complemento sea redundante. Sin embargo, todavía se puede usar para versiones anteriores de jQuery ".
Mathias Bynens el
Entonces, ¿cómo se publica jQuery 1.4.3, seleccionar un objeto por el valor de su objeto de datos? Lets II quería seleccionar en este ejemplo, ¿algún objeto con datos para customerID igual a 22?
Viaje
54
Además, si está interesado solo en presencia de un atributo de datos específico, puede hacer esto:$('[data-customerID]')
Darkside
77
Esto no funciona, si el campo de datos fue establecido por jquery (usando .data()), ¿verdad?
Martin R.
330

Para las personas que buscan en Google y desean reglas más generales sobre la selección con atributos de datos:

$("[data-test]")seleccionará cualquier elemento que simplemente tenga el atributo de datos (sin importar el valor del atributo). Incluso:

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

$('[data-test~="foo"]')seleccionará cualquier elemento donde el atributo de datos contenga foo pero no tenga que ser exacto, 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"]')seleccionará cualquier elemento donde el valor exacto del atributo de datos sea the_exact_value, por ejemplo:

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

pero no

<div data-test="the_exact_value foo">This won't match</div>
JTG
fuente
21
Bueno. Tenga en cuenta que ~=coincide con palabras separadas por espacios en blanco, mientras que *=coincide con cualquier subcadena.
Sam
¿Qué hay del ^personaje?
kuba44
1
@ kuba44, de hecho, también puede usar ^, como tal, $('[data-test^=foo]')en este caso, selecciona cualquier cosa que comience con foo, como <div data-test="foo_exact_value">o <div data-test="food">no<div data-test="seafoo">
JDuarteDJ
Lista completa de selectores de atributos: drafts.csswg.org/selectors-3/#attribute-selectors
user1460043
142

El uso $('[data-whatever="myvalue"]')seleccionará cualquier cosa con atributos html, pero en las nuevas jQueries parece que si usa $(...).data(...)para adjuntar datos, usa algo del navegador mágico y no afecta el html, por lo tanto, no se descubre .findcomo se indica en la respuesta anterior .

Verificar (probado con 1.7.2+) (también ver violín ): (actualizado para ser más 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
fuente
1
aha - resulta que alguien más lo señala en stackoverflow.com/questions/4191386/…
drzaus el
44
y ofrece una solución con .filter aquí
drzaus
22
utiliza algo del navegador mágico y no afecta el html : no existe la magia;) learningjquery.com/2011/09/using-jquerys-data-apis
Tom Sarduy
1
Si está agregando un atributo de datos que necesita encontrar más tarde, use$item.attr('data-id', 10);
Pedro Moreira
77

No he visto una respuesta de JavaScript sin jQuery. Esperemos que ayude a alguien.

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

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

Información:

Sjoerd Pottuit
fuente
1
Gracias por esto. Es bueno ver soluciones que no son jquery.
Chuck el
68

Para seleccionar todos los anclajes con el atributo de datos data-customerID==22, debe incluir el apara limitar el alcance de la búsqueda solo a ese tipo de elemento. Hacer búsquedas de atributos de datos en un bucle grande o en alta frecuencia cuando hay muchos elementos en la página puede causar problemas de rendimiento.

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

Ejemplos nativos de JS

Obtener NodeList de elementos

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

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

Consigue el primer elemento

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

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

Dirigirse a una colección de nodos que devuelve una lista de nodos

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

html:

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

Obtenga elementos basados ​​en valores de datos múltiples (OR)

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

html:

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

Obtenga elementos basados ​​en valores de datos combinados (Y)

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

html:

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

Obtenga elementos donde el valor comienza con

document.querySelectorAll('[href^="https://"]')
etoxina
fuente
El selector para "obtener el primer elemento" es correcto pero no es coherente con los otros ejemplos. Creo que faltan "datos".
GuyPaddock
15

a través del 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
fuente
¿Probaste el violín? El método de filtro es solo otro enfoque para lograr lo mismo. Puede ser útil cuando ya tiene un conjunto de objetos Jquery y necesita filtrar según el atributo de datos o cualquier otra cosa.
Razan Paul
Mis disculpas, @Blizzard. He comentado la respuesta incorrecta. Pegado a la derecha ahora. #AlwaysALongDayAtWork
Peter Bishop
15

La construcción de esta manera: $('[data-XXX=111]')no funciona en Safari 8.0 .

Si configura el atributo de datos de esta manera: $('div').data('XXX', 111)solo funciona si configura el atributo de datos directamente en DOM de esta manera:$('div').attr('data-XXX', 111) .

Creo que es porque el equipo de jQuery optimizó el recolector de basura para evitar pérdidas de memoria y operaciones pesadas en la reconstrucción del DOM en cada atributo de cambio de datos.

Anton Danilchenko
fuente
Esto me ayudó mucho: si utilicé los datos o los métodos de utilería, la selección por $ ('... [data-x = "y"]') no funcionaba; en su lugar, usé attr (empuja el cambio de atributo a el DOM) Thx
Jarda
13

Para que esto funcione en Chrome, el valor no debe tener otro par de comillas.

Solo funciona, por ejemplo, así:

$('a[data-customerID=22]');
usuario55318
fuente
44
Esto parece ser incorrecto. Al menos no es correcto ahora. Acabo de usar $ ('[data-action = "setStatus"]'). RemoveClass ('disabled'); en Chrome y funciona perfectamente.
Peter Bishop
Supongo que no hay uso de "" dentro del selector, se puede usar como$('[data-action=setStatus]').removeClass('disabled')
Animesh Singh
6

A veces es deseable filtrar elementos en función de si tienen elementos de datos adjuntos mediante programación (es decir, no a través de atributos dom):

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

Lo anterior funciona pero no es muy legible. Un mejor enfoque es usar un pseudo-selector para probar este tipo de cosas:

$.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";
    };
});

Ahora podemos refactorizar la declaración original a algo más fluido y legible:

$el.filter(":hasData('foo-bar')").doSomething();
XDS
fuente
1
La primera solución pierde la declaración de retorno, debe ser: $ el.filter (function (i, x) {return $ (x) .data ('foo-bar');}). DoSomething ();
Salma Gomaa
3

Solo para completar todas las respuestas con algunas características del 'estándar de vida': por ahora (en la era html5) es posible hacerlo sin una biblioteca de terceros:

  • JS puro / simple con querySelector (utiliza selectores CSS):
    • seleccione el primero en DOM: document.querySelector('[data-answer="42"],[type="submit"]')
    • seleccione todo en DOM: document.querySelectorAll('[data-answer="42"],[type="submit"]')
  • CSS puro / simple
    • algunas etiquetas específicas: [data-answer="42"],[type="submit"]
    • todas las etiquetas con un atributo específico: [data-answer]oinput[type]
Sven
fuente