Displaying the information from a nested array of objects in an HTML table through iteration

In the code snippet below, there is an input with a nested array of objects.

The main array of objects is called summary and within it, there's a nested array called run_type.

let input = {
      "summary": [
          {
              "name": "Release",
              "run_type": [
                {
                  "environment": "6nc",
                  "type": "QA1"
                },
                {
                  "environment": "3nc",
                  "type": "QA2"
                }
              ]
          }
      ]
  }

A table needs to be displayed as shown below. The Name field should have a rowspan of 2 due to having 2 run_type values for each summary.

------------------------------------
   Name    | Environment | RunType |
------------------------------------
  Release  |     6nc     |  QA1    |
           |     3nc     |  QA2    |
------------------------------------

To display this table statically, it can be achieved like this:

<table>
  <thead>
    <tr>
      <th>Vertical</th>
      <th>Environment</th>
      <th>RunType</th>
    </tr>
  </thead>
  <tbody>
  <tr>
    <td rowspan="2">Release</td>
    <td>6nc</td>
    <td>QA1</td>
  </tr>
  <tr>
    <td>3nc</td>
   <td>QA2</td>
  </tr>
  </tbody>
</table>

I am trying to dynamically generate this table using the following approach but facing issues in getting all columns beneath the same Name section:

<table>
  <thead>
    <tr>
      <th>Vertical</th>
      <th>Environment</th>
      <th>RunType</th>
    </tr>
  </thead>
  <tbody>
     {input?.summary?.map((project, indx) => {
       return (
         <tr>
           <td rowspan="2">{project?.name}</td>
             {project?.run_type?.map((runType, indx) => {
                return (
                  <>
                    <td>{runType.environment}</td>
                    <td>{runType.type}</td>
                  </>
                );
             })}
         </tr>
       );
     })}
  </tbody>
</table>

Answer №1

The issue stems from the utilization of a single <tr> element to loop through both the run_type environments and types, resulting in an inaccurate table structure rendering.

To resolve this problem, consider making the following adjustments to your code:

  <tbody>
    {input?.summary?.map((project, projectIndex) => (
      <>
        {project?.run_type?.map((runType, runTypeIndex) => (
          <tr key={`${projectIndex}-${runTypeIndex}`}>
            {runTypeIndex === 0 ? (
              <td rowspan={project.run_type.length}>{project.name}</td>
            ) : null}
            <td>{runType.environment}</td>
            <td>{runType.type}</td>
          </tr>
        ))}
      </>
    ))}
  </tbody>

Answer №2

To ensure each run_type has its own <tr>, the inner loop should be responsible for generating the rows, not the outer loop. To create a <td> with rowspan only for the first row of the project, you can use a conditional statement with indx==0:

input.summary?.map((project) =>
    project.run_type?.map((runType, indx, {length}) =>
        <tr>
           {indx == 0 ? <td rowspan={length}>{project.name}</td> : ''}
           <td>{runType.environment}</td>
           <td>{runType.type}</td>
        </tr>
    )
)

Answer №3

To start, I will convert the data into a matrix containing text and row-span details.

Using this matrix, I can easily generate the content for the <tbody>.

let inputData = {
  "summary": [{
    "name": "Release",
    "run_type": [{
      "environment": "6nc",
      "type": "QA1"
    }, {
      "environment": "3nc",
      "type": "QA2"
    }]
  }]
};

const tableData = inputData.summary.flatMap(({ name, run_type }) => {
  return run_type.map(({ environment, type }, index) => {
    const rowValues = [];
    if (index === 0) {
      rowValues.push({ text: name, rowSpan: run_type.length });
    }
    rowValues.push({ text: environment });
    rowValues.push({ text: type });
    return rowValues;
  });
});

document.querySelector('.data tbody').insertAdjacentHTML('afterbegin', `
  ${tableData.map(row =>
    `<tr>${row.map(col =>
      `<td rowSpan=${col.rowSpan ?? 1}>${col.text}</td>`)
    .join('')}</tr>`)
  .join('')}
`);
table.data {
  border-collapse: collapse;
}

table.data, .data th, .data td {
  border: thin solid grey;
}

.data th, .data td {
  padding: 0.5rem;
}

.data th {
  background: rgba(0, 0, 0, 0.125);
}
<table class="data">
  <thead>
    <tr>
      <th>Name</th>
      <th>Environment</th>
      <th>RunType</th>
    </tr>
  </thead>
  <tbody></tbody>
</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

Switch the PHP-generated image using jQuery

Below is the HTML and Javascript code I am currently using: <script type="text/javascript"> $(function() { $('#form_1 input').on('change', function() { val = $('input:radio[name=graf]:checked').val(); ...

Center a vertically aligned element following a heading, with the content dynamically generated and enclosed in a fixed container

My mind is racing with this problem and I'm not sure if it's solvable, but before throwing in the towel, I thought I'd seek help from the Internet Gods. Here's a visual representation of what I'm aiming for: I want the text to al ...

Enhance your webpage with a stunning background video

I'm trying to add a background video that covers the entire screen but maintains a height of 400px, similar to the one shown here. Is there a way to achieve this without using JavaScript? Below is the HTML code I currently have: <div class="pr ...

Arrange the div and ensure that the external JavaScript file functions properly when the page loads

I am encountering an issue with my JavaScript and CSS code. It works perfectly fine within the fiddle environment but fails to function properly outside of it. Here is the link to the fiddle When I embed the code into an HTML document directly, it does n ...

Enhance user interactivity on your website by incorporating jQuery and CSS for

<table id="tab"> <tr aaa="one" bbb="ooo"><td>xxx</td><</tr> <tr aaa="two" bbb="one"><td>xxx</td><</tr> <tr aaa="three" bbb="one"><td>xxx</td><</tr> ...

Utilizing AngularJS: Triggering a controller function from a directive

I am currently working on a project with a model named 'user', which includes a controller called 'login' and a directive called 'userMenu'. My goal is to have the userMenu directive utilize the 'login' controller th ...

Ways to make JavaScript cycle through a set of images

I'm having trouble trying to set up a code that will rotate multiple images in a cycle for an image gallery I'm working on. So far, I've only been able to get one image to cycle through successfully. Any help or suggestions would be greatly ...

What sets asyncData apart from methods in Nuxt.js?

I am currently utilizing asyncData to fetch data from an API, however it is restricted to pages and cannot be used in components. On the other hand, methods can be used in both pages and components. As these two methods function similarly, I am consider ...

Every time I attempt to send a post request, I receive back only the creation date and the unique objectID

Whenever I send a post request, only the created date and objectID are returned. Whenever I send a post request, only the created date and objectID are returned. This issue persists even after multiple attempts. I attempted to verify it using Postman ...

SystemJS is loading classes that are extending others

In my Angular2 application, I have two classes where one extends the other. The first class is defined in the file course.ts (loaded as js) export class Course { id:string; } The second class is in schoolCourse.ts (also loaded as js) import {Cours ...

What is the best way to extend the final column of a table across the entire width?

Here's the code I'm working with: .frm-find-people table td:nth-child(1) { padding: 5px 15px; width: 100px } .frm-find-people table td:nth-child(2) { border: 1px solid red; } <form class="frm-find-people"> <table> ...

Having difficulty in dynamically loading an image from an API's URL in Angular

In the title, I mentioned that I am utilizing a free API to display cryptocurrency news for my practice project. Everything seems to be working fine except for displaying the images in card view. I will share my code here, so if you have any suggestions on ...

Deactivating elements on a website

Is there a way to prevent multiple transactions due to unintended repeated clicks on a button by disabling all webpage elements when the button is clicked? Suggestions include using a div that can be layered on top of the elements when the button is click ...

Error encountered with the Angular 2 routing system

Currently, I am facing an issue with my Angular 2 router module. Whenever I try to access the link /city, I encounter an error message saying 'ERROR Error: Uncaught (in promise): Error: Cannot activate an already activated outlet Error: Cannot activat ...

Take off the wrapping from the package

I need help with my code on how to remove the wrapper span tag without removing the text. <ul> <li> <a href="#"> </a> <ul> <li> <a href="#"> ...

Can you explain the distinction between using router.METHOD() versus router.route() in Express?

There are two different ways I've come across of writing this code. router.get(path, callback) and router.route(path).get(callback) Based on the surrounding code, they seem to have the same functionality. The documentation for these methods can be ...

"Enhancing User Interaction with jQuery Hover State Dropdown Menus

Here's my issue: I've created a drop-down menu and I want the text color to change when hovering over the menu. Additionally, I'd like the hover state to remain active when hovering over the submenu. Currently, I'm using this code: $( ...

Verify whether a string includes any of the elements within an array

Imagine I have a string: const subject = "This process is flawless" and an array: const matchArray = ["process","procedure","job"] If subject contains any keyword from matchArray, I want to do the following: if (su ...

Tips for extracting a specific segment from a URL string

Take a look at the outcome of the console.log below: console.log('subscribe:', event.url); "https://hooks.stripe.com/adapter/ideal/redirect/complete/src_1E2lmZHazFCzVZTmhYOsoZbg/src_client_secret_EVnN8bitF0wDIe6XGcZTThYZ?success=true" I need to ...

The Axios frontend appears to have difficulty sending request parameters to the backend server

One of the challenges I encountered while working on my frontend with React was setting up a hook to make HTTP requests to fetch data for display. useEffect(() => { const options = { method: "GET", url: `http://localhost:8080/a ...