简体   繁体   中英

How to sort the table and re-generate it with help of pure JavaScript

I need to sort the table by name. For sorting, I use the function

function sortArray(index) {
  let arr = [];
  rows.forEach( elem => {
    arr.push(elem.children[index].textContent); 
  })
  let sort = arr.sort( (a, b) => {
    if ( a > b) {
      return 1;
    }
    if (a < b) {
      return -1;
    }
    return 0;
  });
  console.log(sort);
  return sort;
  }

but I don't know how to redraw the table. Table I create from JSON file dynamically. In order to start sorting, you need to click on the name of the field and then the already sorted table should be displayed.

const buildHeader = data =>
  Object.keys(data)
    .map(k => `<th>${k}</th>`)
    .join("");
const buildRow = data =>
  Object.keys(data)
    .map(k => `<td>${data[k]}</td>`)
    .join("");
let element = document.querySelector(".people");

function showPeople(people) {
  let table = document.createElement("table");
  table.classList.add("people__table");
  let thead = document.createElement("thead");
  thead.innerHTML = `<tr class="head">${buildHeader(people[0])}</tr>`;
  table.appendChild(thead);
  let tbody = document.createElement("tbody");
  tbody.innerHTML = people
    .map(p => `<tr class="person">${buildRow(p)}</tr>`)
    .join("");
  table.appendChild(tbody);
  element.appendChild(table);
}

const customPeople = data =>
  data.map((p, i) => {
    return {
      name: p.name,
      sex: p.sex,
      born: p.born,
      died: p.died,
      age: p.died - p.born,
      mother: p.mother,
      father: p.father,
    };
  });

showPeople(customPeople(ANCESTRY_FILE));

Something like this sortTable function would do the job:

 function sortTable(tbody, index, ascending) { Array.prototype.slice.call(tbody.children).sort( (tr1, tr2) => tr1.children[index].textContent.localeCompare(tr2.children[index].textContent) * (ascending ? 1 : -1) ).forEach(tr => tbody.appendChild(tr)); } // demonstration (function(){ const thead_tr = document.getElementById('thdtr'); const tbody = document.getElementById('tbd'); function makeCell() { const td = document.createElement('td'); td.appendChild(document.createTextNode(Math.round(Math.random() * 999999999).toString(36))); return td; } function makeRow() { const tr = document.createElement('tr'); for(let i = 0; i < thead_tr.children.length; i++) tr.appendChild(makeCell()); return tr; } // adds click-to-sort functionality Array.prototype.forEach.call(thead_tr.children, (th, index) => { let asc_toggle = false; // false will start off in ascending order th.addEventListener('click', event => sortTable(tbody, index, asc_toggle = !asc_toggle)); }); // fills the table with random alphanumeric data for(let i = 0; i < 100; i++) tbody.appendChild(makeRow()); }()); 
 <table> <thead> <tr id="thdtr"> <th>col 1</th> <th>col 2</th> <th>col 3</th> </tr> </thead> <tbody id="tbd"> </tbody> <table> 

My sortTable function is a generic in-place table sorting function that should work on any table. It accepts 3 parameters:

  1. tbody - DOMElement - A reference to either the tbody element or the table element itself, whichever contains the tr (row) elements.
  2. index - Number - The index of the column to sort by (starts at 0 ).
  3. ascending - Boolean - Whether the order is ascending ( true ) or descending ( false )

Example usage for use with your current code:

sortTable(document.querySelector('.people__table tbody'), 0, true);

You could reappend the rows to the tables body:

 const body = document querySelector(".people__table > tbody");

 for(const el of sort)
   body.appendChild(el);

Or you just sort the data and regenerate the whole table.

Please find the example below:

 let data = generateData(); let columns = [ { name: "id", callback: function() { flags.id *= -1; doSortInt("id", flags.id); } }, { name: "name", callback: function() { flags.name *= -1; doSortStrings("name", flags.name); } }, { name: "age", callback: function() { flags.age *= -1; doSortInt("age", flags.age); } } ]; var flags = { id: -1, name: -1, age: -1 }; createBasicTable(columns); populateDataToTable(data); function doSortInt(prop, flag) { data.sort(function(a, b) { return flag * (b[prop] - a[prop]); }); populateDataToTable(data); } function doSortStrings(prop, flag) { data.sort(function(a, b) { return flag * ("" + a[prop]).localeCompare(b[prop]); }); populateDataToTable(data); } /** * This function is used to fill in the table with data from array */ function populateDataToTable(data) { let tableBody = document.querySelector("#table-body"); // remove all childs while (tableBody.firstChild) { tableBody.removeChild(tableBody.firstChild); } // add new data data.forEach(function(el) { let tr = document.createElement("tr"); let th1 = document.createElement("th"); th1.innerHTML = el.id; tr.appendChild(th1); let th2 = document.createElement("th"); th2.innerHTML = el.name; tr.appendChild(th2); let th3 = document.createElement("th"); th3.innerHTML = el.age; tr.appendChild(th3); tableBody.appendChild(tr); }); } /** * This function is used to create a basic empty table */ function createBasicTable(columns) { let element = document.querySelector("#table-container"); let table = document.createElement("table"); table.classList.add("people__table"); let thead = document.createElement("thead"); let tr = document.createElement("tr"); columns.forEach(function(col) { let th = document.createElement("th"); th.classList.add("head"); th.innerHTML = col.name; th.addEventListener("click", col.callback); // add listener here tr.appendChild(th); }); thead.appendChild(tr); table.appendChild(thead); let tbody = document.createElement("tbody"); tbody.id = "table-body"; table.appendChild(tbody); element.appendChild(table); } /** * This function is used to generate some data for the table */ function generateData() { let data = []; for (var i = 0; i < 100; i++) { let obj = { id: i, name: "Name_" + (i + 1), age: 30 + i * 2 }; data.push(obj); } return data; } 
 <!DOCTYPE html> <html class="no-js"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title></title> <meta name="description" content="" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> </head> <body> <div id="table-container"></div> </body> </html> 

The main points are:

In column definitions array you have callbacks for each column header. Then you call the function

createBasicTable

which creates an empty table without data. And in this function you registers the column headers callbacks. Then you have a function

populateDataToTable

which takes an array as a parameter and uses this array to build table rows. Finally, in your callbacks, you just need to sort your data array properly and update the table content with function:

populateDataToTable

ps Code is not prefect, but it should at least give you a hint, how to implement this functionality. I will try to improve the code tomorrow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM