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

Poorly positioned text displayed inline in HTML

My attempt to place a title in a div toolbar next to some images has hit a snag. The text is not aligning correctly; it should be positioned at the top of the toolbar, but it stubbornly remains at the bottom without budging. I wish for it to be vertically ...

The TD border is slicing through the div and is placed on the table in IE standards, causing it

Below is the HTML code where the div is being cut by the table border when the page is in standards mode. Interestingly, if I remove the <!DOCTYPE html>, then it works fine as expected. The issue of the outside div not behaving properly on the table ...

Exploring the process of incorporating a JavaScript library into an Angular project

I've encountered this issue before and know there are various workarounds available. I often search online for front-end design code to enhance the user experience of my projects, such as carousels, animations, and more. However, most of these project ...

React does not automatically re-render components created with the built-in function

I'm facing some confusion with the behavior in my code: I've created a component that should function as a menu using MaterialUI. The idea is that when a button in the menu is clicked, it becomes "active" and visually reflects this change by set ...

Passing data as a parameter to a page in React using history push

My Ionic React application includes functionality where the history.replace method is used to redirect users from the settings page to the login screen upon clicking a logout button. I am looking for a way to include a loggedOut flag in the redirection pro ...

The value stored within an object does not automatically refresh when using the useState hook

const increaseOffsetBy24 = () => { setHasMore(false); dispatch(contentList(paramsData)); setParamsData((prevState) => ({ ...prevState, offset: prevState.offset + 24, })); setHasMore(true); }; This function increment ...

Enhancing Graphics with Anti Aliasing in Three.js and WebGL

While spinning my model with an orbiter, I am experiencing some issues with anti-aliasing. Currently, I am using the following renderer: renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true, antialias: true }) ...

Filter an array using an algorithm inspired by Binary Search Trees

I am facing a challenge with a sorted array of dates, here is an example: let arr = ['2019-03-12', '2019-02-11', '2019-02-09', '2018-06-09', '2018-01-24', ..] The arr has a length of 100,000, and I need t ...

Using Lazy Load Plugin for jQuery to enhance Backbone.js functionality

I am working on a Backbone.js application using require.js and underscore.js. I am trying to incorporate the jquery lazy loading plugin with the Eislider banner. The Eislider banner was functioning properly before implementing the lazy loading script. Th ...

Pair participants within a game search array

I've been contemplating this issue extensively but I'm struggling to come up with a fast and efficient solution using JavaScript. I have an array of objects representing game searches for random players. The array might resemble the following: co ...

Tips for including the % symbol in the Y-axis labels on a HighChart graph

I am attempting to incorporate the % symbol after the value of 100 or -100 on the yAxis in the chart shown above. I made an attempt to add the % symbols as follows: quotes.data.frequency_counts[i].negative = Math.round(negative * -1)+'%'; quote ...

What are some ways to make autorun compatible with runInAction in mobx?

Currently delving into the world of mobx and runInAction, facing a challenge in comprehending why autorun fails to trigger my callback in this particular scenario: class ExampleClass { // constructor() { // this.exampleMethod(); // } ...

Using Typescript: How to access a variable beyond the scope of a loop

After creating an array, I need to access the elements outside of the loop. I am aware that they are not in the scope and using 'this.' before them does not grant access. colIdx = colIdx + this.columns.findIndex(c => c.editable); this.focusIn ...

Duplicate multiple "li" elements using jQuery and place them in a designated position within the ul element, rather than at the end

I am currently working on developing a dynamic pagination bar. This pagination bar will dynamically clone the "li" elements based on a number received from an external webservice. Here is the structure of my pagination element: <ul class="pagination"& ...

JavaScript Nested Array Looping Script

I am currently working on a loop script for my application that checks for the full capacity of a user array and adds a user ID if there is space available. The data in my JSON file is structured around MongoDB and contains 24 entries (hours). Each entry ...

Dynamic website where each page is loaded based on the user's previous interaction

Can I get your opinion on something? I'm currently working on an ajax webpage. The links on my page make a GET request to the URL they are linked to, extract the div.content, and then update the content of the current div.content. Strangely, this GET ...

Difficulty arises when trying to extract specific information from an ajax response using the jQuery.filter

The code snippet below seems to be causing some trouble. It's supposed to filter HTML content that includes a div with the class "filtered_entries_box", but it's not working as expected. $.ajax({ "url" : "start.php", "type" : "POST", ...

triangle shape filled with a gradient that transitions between two colors

I have two triangles displayed at the bottom of my page - one on the left and one on the right. The right triangle is currently transparent but I want to add a gradient effect to it. For the triangle-bottom-right, I'd like the gradient to go from rgb ...

From time to time, I may post files of substantial size

When moving to the next step in the form, I have implemented checks to prevent photos over 10mb and disallow .heic files from being uploaded. Most of the time it works as expected, but occasionally files slip through. If anyone has suggestions for a more ...

Reverse changes made to a massive object and then redo them

My current project requires the implementation of undo-redo functionality for a product. At the moment, I am managing a substantial Object retrieved from a MongoDB collection The structure is as follows: { cart:{ products:[ { name: " ...