Tengo una serie de divs que muestran datos sobre diferentes personas. Los datos de cada persona se almacenan en una matriz de objetos y hay muchos valores para cada persona. Hay un botón para cada propiedad, y me gustaría poder ordenar los divs en orden ascendente o descendente de una propiedad haciendo clic en un botón. Cada div recibe una identificación, que corresponde a una identificación de la persona asociada en la matriz.
Los datos se ven así (pero es mucho más grande que esto):
people = [ { id: 'xde234', height: '196', weight: '100', age: '34' }, { id: 'sbd451', height: '176', weight: '140', age: '26' }, { id: 'loe489', height: '156', weight: 'NA', age: '54' }]Los datos de cada persona se muestran recorriendo los datos, creando un div para cada persona, asignando su id como el id del div y definiendo el html interno de un intervalo con cada valor de propiedad. El nombre de clase del tramo es el mismo que el de la propiedad. Entonces el HTML se ve así:
<div id="peopleContainer"> <div id='xde234'> <span class="height">196</span> <span class="weight">100</span> <span class="age">34</span> </div> <div id='sbd451'> <span class="height">176</span> <span class="weight">140</span> <span class="age">26</span> </div> <div id='loe489'> <span class="height">156</span> <span class="weight">NA</span> <span class="age">54</span> </div> </div>Cada botón se crea con un detector de eventos, por ejemplo:
heightButton = document.getElementById('heightButton') heightButton.addEventListener('click', function(){ // sortingFunction }He estado recuperando los divs y escribiendo una función de clasificación usando:
function sortingFunction(property){ peopleContainer = document.getElementById('peopleContainer') allPeople = peopleContainer.children }Realmente tengo 3 preguntas, siendo la principal la primera:
¿Cuál es la forma más eficiente de ordenar y mostrar estos datos en javascript para cualquier propiedad en los datos, considerando que habrá muchas personas y una gran cantidad de propiedades?
¿Cómo implemento la ordenación ascendente y descendente en un botón, para que alternen entre los dos?
Cuando se hace clic en un botón, independientemente de si es ascendente o descendente, me gustaría que todos los valores NA estuvieran en la parte inferior, es decir, se ignoran en la ordenación pero se agregan al final.
Cualquier ayuda es muy apreciada.
Puede ser útil crear una nueva estructura de datos que contenga referencias a los elementos DOM.
const peopleElements = {} [...allPeople].forEach(node=>{ peopleElements[node.id] = node; }); A continuación, puede ordenar su matriz de people como desee. Una vez hecho esto, puede actualizar el contenedor:
people.forEach(person=>{ const node = peopleElements[person.id]; peopleContainer.append(node); });Tenga en cuenta que agregar un elemento que ya está en la página simplemente lo moverá al final. Mover a cada persona hasta el final hará que los elementos aparezcan ordenados.
gracias a @NiettheDarkAbsol, su respuesta combinada con las siguientes funciones de clasificación me ha llevado a una respuesta funcional. Uso el atributo de datos para almacenar el último tipo de clasificación (asc o desc). Utilizo la sugerencia de @NiettheDarkAbsol para agregar nodos, pero lo hago dos veces, la segunda vez con una condición para verificar los NA, luego muévalos al final, lo que funciona como se desea. La función de clasificación ahora es:
function sortingFunction(e, property){ peopleContainer = document.getElementById('peopleContainer'); allPeople = peopleContainer.children; const peopleElements = {}; [...allPeople].forEach(node=>{ peopleElements[node.id] = node; }); if(e.target.getAttribute('data-lastSort') === 'desc'){ e.target.setAttribute('data-lastSort','asc') people.sort(function(a,b){ return a[property] - b[property] }); }else{ e.target.setAttribute('data-lastSort','desc') people.sort(function(a,b){ return b[property] - a[property] }); }; people.forEach(person=>{ const node = peopleElements[person.id]; peopleContainer.append(node); }; people.forEach(person=>{ if(person[property] === 'NA'){ const node = peopleElements[person.id]; peopleContainer.append(node); }; }); };