What is the best way to convert an HTML table into an array of objects?

In my Angular Protractor end-to-end (e2e) tests, I need to perform assertions on an HTML fragment similar to the following:

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Age</th>
            <th>Gender</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Joe</td>
            <td>23</td>
            <td>M</td>
        </tr>
        <tr>
            <td>Mary</td>
            <td>26</td>
            <td>W</td>
        </tr>
        ...
    </tbody>
</table>

Is there a way to transform this into a JavaScript object in the following format?

[
    {Name: 'Joe', Age: 23, Gender: 'M'},
    {Name: 'Mary', Age: 25, Gender: 'W'},
    ...
]

I attempted the following approach, however, it only returns a one-dimensional array:

const row = element.all(by.css('tr'));
const cells = row.all(by.tagName('td'));
return cells.map(function (elm) {
  return elm.getText();
});

Answer №1

To tailor it to your specific situation, you have the option to transform the HTML content into a straightforward array of objects that align with your requirements:

function isHTMLTableElement(elem: HTMLTableElement | HTMLElement) : elem is HTMLTableElement {
    return elem.tagName === 'TABLE';
}

const table = document.getElementById('test');
const result: {name: string, age: number, gender: string}[] = [];

if (isHTMLTableElement(table)) {
    const rows: HTMLElement[] = [].slice.call(table.querySelectorAll('tbody tr'));
    for (const row of rows) {
        const cells: HTMLElement[] = [].slice.call(row.querySelectorAll('td'));
        const [name, age, gender] = cells.map(c => c.innerText);
        result.push({
            name: name,
            age: +age,
            gender: gender
        });
    }

    console.log(JSON.stringify(result));
}

For a more concise code snippet, you could streamline it by substituting for loops with array methods. However, in its current form, it may be easier to comprehend.

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

Sequelize makes it easy to input records into various tables simultaneously

Embarking on my first experience with Sequelize and MySQL, I am seeking guidance on inserting data into two tables with a foreign key relationship. Let's delve into the structure of the entities - bookingDescription and bookingSummary. //bookingSumma ...

Switching over from create-react-app to NextJS, encountering difficulties with integrating ThreeJS

A while back, I had successfully implemented a 3D model viewer in React. Now, I'm facing a challenge as I try to migrate this project to Next.js. The specific issue lies with the GLTFLoader and OrbitControls dependencies that were previously imported ...

observe the file currently residing on the server

Is there a way to display a server-based file within an HTML page using Angular 8.0.0? I attempted to use ngx-file-viewer, but encountered the error "Property 'wheelDelta' does not exist on type 'WheelEvent'". To address this issue, I ...

Is it possible for Cypress to execute test files that are imported from outside of the Cypress folder

Currently, I am developing an E2E test framework using Cypress and encountered an issue while trying to import spec files from locations outside the traditional Cypress directory structure (which includes directories for fixtures, integration, plugins, and ...

Separating the login/register functionality from the main app using the MEAN Stack

Apologies for my poor English! I have developed an application using the MEAN stack (MongoDB + Express.js + Angular.js + Node.js) with authentication utilizing passport.js and JWT (jsonwebtoken and express-jwt). What I aim to achieve? The login and r ...

What is the best way to ensure a jQuery function runs on duplicated elements?

I have been attempting to construct a webpage featuring cascading dropdowns using jQuery. The goal is to generate a duplicate set of dropdowns when the last dropdown in the current set is altered. I aim for this process to repeat up to 10 times, but I cons ...

Tips for accessing form data that has been automatically uploaded in PHP

I've been trying to automatically post data using JavaScript and retrieve it in a PHP file. However, I am facing an issue where the PHP file is not able to retrieve the data. I have set up an automatic form that takes input from another form and send ...

Is it possible for a memory leak to occur when a jQuery object is created within a function but never actually used?

As an illustration: function calculateTime(minutes) { var newTime = new Date(); newTime.setHours(0, minutes, 0, 0); return angular.element('<input type="hidden"/>').timepicker('setTime', newTime).val(); } I'm cu ...

JavaScript HTML content manipulation

Why doesn't this code work? innerHTML cannot handle something so complex? <html> <head> <script type="text/javascript"> function addTable() { var html = "<table><tr><td><label for="na ...

Utilizing database information for interactive objects in Three.js: A step-by-step guide

I need to display specific text data for each object based on database entries in my project. However, despite creating a cube for each entry in the database, I'm encountering issues with undefined data. It seems like my code should work, but it' ...

Reorganizing array sequence within a sortable list

I'm currently working with the react-beautiful-dnd module to build a draggable list. The backend data I receive is arranged according to the sequence field. Once an item is dragged and dropped, I utilize the reorder function to generate a new list. Ho ...

Using TypeScript to automatically determine the argument type of a function by analyzing the return type of a different function

I am working on an interface with the following structure: interface Res<R = any> { first?(): Promise<R>; second(arg: { response: R }): void; } However, I noticed that when creating a plain object based on this interface, the response ...

Error: Uncaught promise rejection - The function is undefined in the context of Vue.js and Electron

I've been experimenting with anime.js to animate elements using promise functions. However, I'm encountering an issue where the second function does not run after the previous one successfully completes. <script> import Splash from '. ...

Handling Removal of Selected Option in React Material-UI Autocomplete Single Selection

I am currently using material UI autocomplete to create a single-select dropdown. However, I have encountered an issue wherein the onChange event does not get triggered when I click the close button on the right side of the input. This prevents my state fr ...

Vue and Jexcel: maximizing efficiency with event handling and dynamic calculations

I am trying to utilize the vue wrapper for jexcel and want to trigger the undo function from the toolbar computed field. However, I am facing difficulties accessing the spreadsheet instance as it throws an error saying 'this.undo is undefined.' ...

Guidelines for utilizing a loader to handle a TypeScript-based npm module

I am currently facing a challenge with my React and JavaScript project as I attempt to integrate an npm module developed with TypeScript. The issue lies in configuring my project to compile the TypeScript code from this module, resulting in the error messa ...

Implement a click event using jQuery specifically for Internet Explorer version 7

How can I add an onclick attribute using jQuery that is compatible with IE7? So far, the following code works in browsers other than IE8 and Mozilla: idLink = Removelst(); var newClick = new Function(idLink); $(test1).attr('onclick', null).clic ...

What is the best way to incorporate Javascript into jQuery tabs?

On my website, I have implemented a Jquery and CSS tab system similar to the one found here. Each tab contains a Facebook feed box, a Twitter widget, and a ranking widget for my blog. However, when these widgets are placed within the tab content area, they ...

Having trouble importing from the src folder in Expo React

I am currently using expo-cli. When I import a module from the 'src' folder (which I created), it works perfectly fine when opened in a web browser, but encounters an error when opened on an Android device. I have tried using absolute paths and ...

Attaching a buoyant div to the precise location of a different element

I have a unordered list (ul) with individual list items (li) that are displayed within a scrollable container. This means that only 8 list items are visible at a time, but you can scroll through them to see the others. Each list item (li) has an "edit" b ...