根据下拉选项对表格进行排序

时间:2018-12-28 10:11:46

标签: javascript html-table

我正在尝试根据用户从下拉列表中选择的排序选项对表进行排序。我遇到了this主题和that一个主题,但是它们都基于jQuery,但是它们似乎都不适合我,因为我需要纯Javascript解决方案。

我的HTML:

<label>Sort order:</label>
<select>
  <option>Item asc</option>
  <option>Item desc</option>
  <option>Price asc</option>
  <option>Price desc</option>
  <option>Year asc</option>
  <option>Year desc</option>
</select>
<table>
<thead>
  <tr>
    <th>item</th>
    <th>price</th>
    <th>year</th>
  </tr>
</thead>
<tbody>
  <tr>
    <td>Skoda Octavia</td>
    <td>7000</td>
    <td>2012</td>
  </tr>
  <tr>
    <td>Toyota Yaris</td>
    <td>3000</td>
    <td>2011</td>    
  </tr>
  <tr>
    <td>Ford Focus</td>
    <td>5000</td>
    <td>2009</td>
  </tr>
</tbody>
</table>

自从我是新来的人,我非常感谢您提供有关如何解决问题的帮助。

2 个答案:

答案 0 :(得分:0)

基本上,您的问题可以分为三个较小的问题:

将HTML表数据放入包含对象数组的javascript对象中,每个对象都具有对应于列标题和单元格值的属性,以便您可以根据属性值对该数组进行排序:

const jsonFromHtml = (tbody, thead) => {
    let tableJson = {rows:[]};
  [...tbody.children].forEach(tableRow => {
    let rowEntry = {};
    [...tableRow.children].forEach((cell, column) => rowEntry[thead.children[0].children[column].textContent] = cell.textContent);
    tableJson.rows.push(rowEntry);
  });
  return tableJson;
};

以任意顺序对行项目进行排序:

const customSort = (arr, key, order) => {
    let sortCompare = order == 'Desc' ? -1 : 1;
  return arr.sort((first, second) => first[key]>second[key] ?  sortCompare : first[key]<second[key] ?  -sortCompare : 0);
};

根据行的排序数组组成表主体内部HTML:

const arrayToTable = (arr, tbody, thead) => {
    let rows = [];
    arr.forEach((row, rowNum) => {
    row = [...thead.children[0].children].map(th => row[th.textContent] ? row[th.textContent] : '');
    row = row.map(td => `<td>${td}</td>`);
    row = `<tr>${row.join('')}</tr>`;
    rows.push(row);
  });
  tbody.innerHTML = rows.join('');
};

const myTableTbody = document.querySelector('#myTable tbody');
const myTableThead = document.querySelector('#myTable thead');

const jsonFromHtml = (tbody, thead) => {
	let tableJson = {rows:[]};
  [...tbody.children].forEach(tableRow => {
    let rowEntry = {};
    [...tableRow.children].forEach((cell, column) => rowEntry[thead.children[0].children[column].textContent] = cell.textContent);
    tableJson.rows.push(rowEntry);
  });
  return tableJson;
};

const customSort = (arr, key, order) => {
	let sortCompare = order == 'Desc' ? -1 : 1;
  return arr.sort((first, second) => first[key]>second[key] ?  sortCompare : first[key]<second[key] ?  -sortCompare : 0);
};

const arrayToTable = (arr, tbody, thead) => {
	let rows = [];
	arr.forEach((row, rowNum) => {
  	row = [...thead.children[0].children].map(th => row[th.textContent] ? row[th.textContent] : '');
    row = row.map(td => `<td>${td}</td>`);
    row = `<tr>${row.join('')}</tr>`;
    rows.push(row);
  });
  tbody.innerHTML = rows.join('');
};

document.querySelector('#selectionOrder').addEventListener('change', function(){
	let sortKey = this.value.match(/[a-z]+/)[0];
  let sortOrder = this.value.match(/(A|De)sc/) ? this.value.match(/(A|De)sc/)[0] : 'Asc';
  let myTableJson = jsonFromHtml(myTableTbody, myTableThead);
  myTableJson.rows = customSort(myTableJson.rows, sortKey, sortOrder);
  arrayToTable(myTableJson.rows, myTableTbody, myTableThead);
});
<label>Sort order:</label>
<select id="selectionOrder">
  <option value="itemAsc">Item asc</option>
  <option value="itemDesc">Item desc</option>
  <option value="priceAsc">Price asc</option>
  <option value="priceDesc">Price desc</option>
  <option value="yearAsc">Year asc</option>
  <option value="yearDesc">Year desc</option>
</select>
<table id="myTable">
<thead>
  <tr>
    <th>item</th>
    <th>price</th>
    <th>year</th>
  </tr>
</thead>
<tbody>
  <tr>
    <td>Skoda Octavia</td>
    <td>7000</td>
    <td>2012</td>
  </tr>
  <tr>
    <td>Toyota Yaris</td>
    <td>3000</td>
    <td>2011</td>    
  </tr>
  <tr>
    <td>Ford Focus</td>
    <td>5000</td>
    <td>2009</td>
  </tr>
</tbody>
</table>

答案 1 :(得分:0)

这是一种解决方案,它可以在变量中定义数据,然后从中构建HTML。

// Define data in variables, not in HTML:
const columns = ["item", "price", "year"];
const data = [
    { "item": "Skoda Octavia", "price": 7000, "year": 2012 }, 
    { "item": "Toyota Yaris",  "price": 3000, "year": 2011 }, 
    { "item": "Ford Focus",    "price": 5000, "year": 2009 }, 
]

// Elements in the DOM
const orderSelect = document.getElementById("orderSelect");
const dataTable = document.getElementById("dataTable");

// Populate select list based on the columns of the data
for (const column of columns) {
    for (const dir of [" asc", " desc"]) {
        const opt = document.createElement("option");
        opt.value = opt.text = column + dir;
        orderSelect.add(opt);
    }
}

function refreshTable() {
    const [sortBy, order] = orderSelect.value.split(" ");
    const sign = order === "asc" ? -1 : 1;
    data.sort((a, b) => a[sortBy] < b[sortBy] ? sign : a[sortBy] > b[sortBy] ? -sign : 0);
    // Clear table
    dataTable.innerHTML = ""; 
    // Create header row
    const row = dataTable.insertRow(-1);
    for (const column of columns) {
        const th = document.createElement("th");
        th.textContent = column;
        row.appendChild(th);
    }
    // Create data rows
    for (const record of data) {
        const row = dataTable.insertRow(-1);
        for (const column of columns) {
            const td = row.insertCell(-1);
            td.textContent = record[column];
        }
    }
}

// Populate data table
refreshTable();

// handler
orderSelect.addEventListener("change", refreshTable);
<label for="orderSelect">Sort order:</label>
<select id="orderSelect"></select>
<table id="dataTable"></table>