Arrange the table according to the option selected in the dropdown menu

Attempting to organize my table according to the sorting choice selected by the user from a drop-down menu. I encountered this discussion and also that one, both relying on jQuery. However, none of them seem to be effective for me since I require a pure Javascript solution.

Here is a snippet of my 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>

Being new at this, any guidance on how to tackle the issue would be highly appreciated.

Answer №1

Your issue can essentially be broken down into three smaller tasks:

First, you need to convert the data in your HTML table into a JavaScript object that contains an array of objects. Each object should have attributes corresponding to the column headers and cell values so that you can easily sort the array based on these attribute values:

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;
};

The next step is to sort the row-items in any order you'd like:

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);
};

Lastly, you'll need to generate the inner HTML for your table body based on the sorted array of rows:

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('');
};

If you want to apply this functionality to your own table, make sure to update the IDs and content accordingly:

Answer №2

One approach to organizing and displaying data involves defining the information in variables before constructing the HTML.

// Storing data in variables rather than directly within the HTML structure:
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 }, 
]

// Accessing DOM elements
const orderSelect = document.getElementById("orderSelect");
const dataTable = document.getElementById("dataTable");

// Dynamically generating select options based on column names
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 existing table content
    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);
    }
    // Generate 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];
        }
    }
}

// Fill data table with initial content
refreshTable();

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Do GPU-intensive animations get impacted by the CPU's load?

I have set up a special compositing layer for a div with the following unique styles: div { position: absolute; height: 50px; width: 50px; background: #900; top: 100px; left: 200px; will-change: transform; transform: translateZ(0); } Afte ...

CSS magic: Text animation letter by letter

I have a <div> with text. <div> to be revealed on the page one character at a time:</p> <div>, the animation should stop and display the full text instantly.</p> In summary, I aim to replicate an effect commonly seen in Jap ...

Combining and mapping arrays in Javascript to form a single object

I am using the following firebase function this.sensorService.getTest() .snapshotChanges() .pipe( map(actions => actions.map(a => ({ [a.payload.key]: a.payload.val() }))) ).subscribe(sensors => { ...

Lagging speeds in client-side template rendering using Rivets.js

I have a function that renders an array of around 1000 objects, but the html bindings are causing significant performance issues. It currently takes about 5 seconds to complete rivets.bind(). Does anyone have any recommendations for improving performance? ...

Develop the react application: Determine the script tag URL based on the environment

We are working on a React application built with create-react-app. In order to incorporate an external script, we need to add a script tag within the head section of the public/index.html file. The provider of the script has given us two different snippet ...

Execute a function upon pressing the enter key

Currently, I am working on coding a webpage with a form that includes one field where users input a set of numbers. After typing in the numbers, they should then press a button labeled 'Run' to execute the code. However, the issue arises when use ...

The JSX function seems to be malfunctioning, as the function part is not displaying on the webpage as intended

This code snippet is a part of a React component in a project. I have imported a CSS file for styling and have already integrated Material UI. However, the function for the new article is not displaying on the webpage as expected. import "./Widgets. ...

Error message: "When namedPlaceHolder parameter is disabled, bind parameters must be in the form of an

Currently revamping my query due to a crucial API redesign. With the presence of a "file" as multipart/form-data, I found the need for a form handler since NextJS lacked one. After some workarounds with "multiparty", now I can successfully parse the incomi ...

The presence of a Bootstrap addon is resulting in horizontal scrolling on mobile devices within the webpage

I am encountering a peculiar issue with an input-group in my cshtml file which features a Bootstrap addon. The problem arises on mobile devices, where upon focusing on the input field, the page scrolls horizontally to the right, revealing the right margin ...

The mongoose fails to establish a connection with the Mongo Db Atlas

I am having issues with my simple node express app when trying to connect to MongoDB atlas. Despite deleting node_modules and re-downloading all packages, I am still encountering the same error. The specific error message reads as follows: Cannot read pro ...

Stop the form from submitting when the Enter key is pressed

I am experiencing an issue with my form that contains around 10 input text boxes. When I press the enter key from an input text box, it skips the text boxes in between and goes directly to the submit button. This problem occurs only when using the keyboard ...

Preventing touchstart default behavior in JavaScript on iOS without disrupting scrolling functionality

Currently experimenting with JavaScript and jQuery within a UIWebView on iOS. I've implemented some javascript event handlers to detect a touch-and-hold action in order to display a message when an image is tapped for a certain duration: $(document) ...

Execute a PHP function through an AJAX request to dynamically update a template variable in PHPBB

Should you require a condensed version of the details provided below, do not hesitate to ask for a summary. My objective is to execute a function in my PHP file which will update a template variable. Here is an example of such a function: function get_ve ...

Exploring ways to customize the input color of Material UI TextField when it is disabled [Version: 5.0.8]

I am having trouble changing the border color and text color when an input is disabled. I have tried multiple variations, as seen below: const textFieldStyle = { '& label': { color: darkMode?'#1976d2':'', } ...

How to Retrieve Grandparent Component Attributes in Angular Using Grandchild Components

I am constructing an Angular application and facing the challenge of accessing a property of Component 1 within Component 3. In this scenario, the relationship is described as grandparent-grandchild. Successfully establishing communication between parent/ ...

Components undergo a style transformation with Material UI

I've noticed that every time I render the component, the styles keep changing. import React from 'react'; import FormControl from '@material-ui/core/FormControl'; import MenuItem from '@material-ui/core/MenuItem'; im ...

The function is not valid due to an angular-parse argument

This is my first experience with using angular and parse.com. I encountered the following error: Error: Argument 'eventList' is not a function, got undefined when attempting to execute the following angular code: var main_app = angular.mod ...

Unable to add MySQL results to the array

This is the code I am working on: var nbu = req.body.nbu; var inv=[]; db.query( "SELECT * FROM `invoice_ska` WHERE nm_client =?", nbu, (err, results) => { if (err) throw err; inv.push(results); } ); console.log(inv);//this just [] }); I ...

Using three.js to add an image onto an already existing object

I attempted to modify the appearance of an object by adding an image, but all my tests resulted in a white object... The goal is simply to apply an image to the entire object. Here is my test code: var obj = scene.getObjectByName('wall_20_118') ...

Aligning a table at the center of another table

Frustration has been brewing within me all week as I grapple with the task of sending out an important emailer soon. The challenge lies in aligning these product images next to their descriptions at the center, a feat that seems impossible to achieve withi ...