【问题标题】:Sort table based on dropdown option根据下拉选项对表格进行排序
【发布时间】:2018-12-28 10:11:46
【问题描述】:

我正在尝试根据用户从下拉列表中选择的排序选项对表格进行排序。我遇到了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>

由于我是新手,我将不胜感激任何有关如何解决问题的帮助。

【问题讨论】:

  • 请提供您迄今为止在 javascript 中尝试过的内容
  • 您应该首先学习如何从静态 JSON 数据或您喜欢的任何其他格式构建表格,然后您应该根据您的数据对表格进行排序。

标签: javascript html-table


【解决方案1】:

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

将您的 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>

【讨论】:

  • 太棒了!这甚至超出了我的预期。谢谢。
【解决方案2】:

这是一个在变量中定义数据并从中构建 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 2017-05-02
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多