Creating a dynamically expanding rowspan table using VueJS and an associative array with 5 levels of depth

This challenge appears to be quite daunting, but let's dive in

Essentially, I have an associative array that can be altered based on various filters (columns may appear or disappear depending on the selected filters). Additionally, there is a table with dynamic "rowspan" (resulting in a potentially lengthy right side), created based on this array.

 {
  "countries": {
    "25": {
      "title": "France",
      "cities": {
        "8954": {
          "title": "Paris",
          "languages": {     <- Another object - "districts" can be added here
            "16": {
              "title": "English",
              "quarters": {
                "2_2020": {
                  "title": "% 2020-2021",
                  "parallels": {
                    "1": {
                      "title": "tst1"
                    },
                    "2": {
                      "title": "tst2",
                      "value": 7.89
                    },
                    "3": {
                      "title": "tst3",
                      "value": 37.2
                    },
                    "4": {
                      "title": "tst4",
                      "value": 9.16
                    },
                    "5": {
                      "title": "tst5",
                      "value": 6.45
                    }
                  }
                },
                "3_2020": {
                  "title": "% 2019-2020",
                  "parallels": {
                    "1": {
                      "title": "tst1"
                    },
                    "2": {
                      "title": "tst2",
                      "value": 8.59
                    },
                    "3": {
                      "title": "tst3",
                      "value": 9.1
                    },
                    "4": {
                      "title": "tst4",
                      "value": 6.8
                    },
                    "5": {
                      "title": "tst5",
                      "value": 75.1
                    }
                  }
                }
              }
            },
            "1000": {
              "title": "Spanish",
              "quarters": {
                "2_2020": {
                  "title": "% 2020-2021",
                  "parallels": {
                    "1": {
                      "title": "tst1"
                    },
                    "2": {
                      "title": "tst2",
                      "value": 2.75
                    },
                    "3": {
                      "title": "tst3",
                      "value": 41.2
                    },
                    "4": {
                      "title": "tst4",
                      "value": 6.97
                    },
                    "5": {
                      "title": "tst5",
                      "value": 74.4
                    }
                  }
                },
                "3_2020": {
                  "title": "% 2019-2020",
                  "parallels": {
                    "1": {
                      "title": "tst1"
                    },
                    "2": {
                      "title": "tst2",
                      "value": 8.51
                    },
                    "3": {
                      "title": "tst3",
                      "value": 99.1
                    },
                    "4": {
                      "title": "tst4",
                      "value": 75.8
                    },
                    "5": {
                      "title": "tst5",
                      "value": 25.11
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

The desired JSON structure looks like this, or if the "districts" object exists, it should resemble this

Below is my Vue.js code for creating only the body of a table, utilizing another object called "district"

<b-tr v-for="(itemCountry, indexCountry) in itemsReal.countries" :key="indexCountry">
  <b-tr v-for="(itemCities, indexCities) in itemCountry.cities" :key="indexCities" class="w-25 ">
    <b-th class="w-25">{{ itemCities.title }}</b-th>
      <b-tr v-for="(itemDistrict, indexDistricts) in itemCities.districts"  :key="indexDistricts">
        <b-td class="w-25 sticky-sidebar-district">{{ itemDistrict.title }}</b-td>
          <b-tr class="language-rows" v-for="(itemLanguages, indexLanguages) in itemDistrict.languages" :key="indexLanguages">
            <b-td class="language sticky-sidebar-language-District">{{ itemLanguages.title }}</b-td>
             <b-tr class="d-inline-flex" v-for="(itemQuarter, indexQuarter) in itemLanguages.quarters">
             <b-td v-for="(currentNumber, indexCurrentNumber) in itemQuarter.testsarr" :key="indexCurrentNumber" class="value-cells">
             {{ currentNumber.value }} {{ currentNumber.value === undefined ? '&shy' : null }}
          </b-td>
        </b-tr>
      </b-tr>
    </b-tr>
  </b-tr>
</b-tr>

Answer №1

That was quite a challenging problem to solve!

Firstly, it's important to note that vue-bootstrap doesn't function exactly like in the example you provided. Simply nesting b-tr and b-td without utilizing scopes won't work. It seems like there might be something missing in your snippet, but even with that included, it wouldn't function correctly.

Secondly, you can't nest trs within tds directly. Instead, you need to utilize rowspan and colspan attributes to structure your table properly in plain HTML (with bootstrap styles). Here is an example of how your table should look:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="02606d6d76717670637242372c332c32">[email protected]</a>/dist/css/bootstrap.min.css" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">

<table class="table table-bordered">
  <tbody>
  <tr>
    <td rowspan="2">country</td>
    <td rowspan="2">cities</td>
    <td rowspan="2">languages</td>
    <td colspan="5">2019-2020</td>
    <td colspan="5">2020-2021</td>
  </tr>
  <tr>
    <td>tst1</td>
    <td>tst2</td>
    <td>tst3</td>
    <td>tst4</td>
    <td>tst5</td>
    <td>tst6</td>
    <td>tst7</td>
    <td>tst8</td>
    <td>tst9</td>
    <td>tst10</td>
  </tr>
  <tr>
   <th rowspan="4">France</th>
   <th rowspan="2">Paris</th>
   <td>english</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
  </tr>
  <tr>
   <td>spanish</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
   <td>empty</td>
  </tr>
  <tr>
   <th rowspan="2">Lyon</th>
   <td>english</td>
   <td>empty</td>
   <td>empty</td>
   <td>...

Due to the intricacies of working with HTML tables, implementing loops in vue can be challenging. However, I was able to find a solution by formatting the data into arrays instead of objects. This makes it easier to access the data and manipulate it. I created a computed function for this purpose, which parses the incoming data. The code includes comments to explain each part of the process.

// Vue instance
new Vue({
  el: "#app",
  data() {
    return {
      countries: { 
        // Data goes here
      }
    }
  },
  computed: {
    formattedCountries() {
      // Format the countries data here
    }
  },
  methods: {
    calculateCountryRowspan(country) {
      // Method to calculate rowspan of country title
    }
  }
})

This revised code computes and formats the table dynamically based on the provided data. It demonstrates effective looping techniques in Vue.js while handling complex table structures.

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

What is causing React to make multiple API calls when loading the page?

I have a page set up with hooks to retrieve data from a third-party API. Once the data is fetched, I perform various calculations on it before passing it as props to the component. However, it appears that the API is being called multiple times for each ca ...

Webpack and terser reveal the names of the source files in the compressed output

Is there a way to stop source filenames from appearing in webpack output even when using Terser for minification? Illustration After minifying my production React app build, the resulting .js output file still contains original source filenames rather th ...

Checking for null values in a filter test in Javascript

Seeking guidance on how to implement null testing in my filter. The current setup works well unless any of the fields contain a "null" value. In such cases, an error is thrown: TypeError: Cannot read property 'includes' of null Thank you in adv ...

The package.json could not be parsed due to an error

I am currently facing an issue while trying to deploy a JavaScript Node.js project on Heroku. Everything works fine on localhost, but upon uploading, I encounter an "unable to parse" error at : ... "engines" : { "node" : ">0.11.9" }, ... The Error Mes ...

Change the height of a div after submitting a form using Django (Python)

I have a registration form with one submit button. Upon clicking submit, if there is an error, the height of the div increases by setting it to height:auto. However, when I click submit, it changes the height of the div (.continer). Strangely, after one ...

Tips for implementing a confirmation dialogue box prior to submitting a form:

As a new developer, I am facing an issue that I believe you can help me with. I want to display a confirmation box before deleting. How can I achieve this in my Ajax code? HTML: <input type='button' class="btn btn-danger delete_button" id="de ...

Pass the ActiveRecord object retrieved in the success of the ajax call in Rails as a parameter to another subsequent

Imagine this scenario: I have a view named "Dashboard" featuring a basic form and a button labeled "Draw Graphs". The goal is to trigger two ajax requests upon clicking the button, fetching the required data from the database for creating two distinct grap ...

I'm facing a challenge with Firebase rules regarding user configurations that should enable read and write access. How can I overcome this hurdle?

Currently, I am logged into my application using GoogleAuthProvider and in my browser as [email protected] https://i.sstatic.net/pn0O4.png The rules for my app project are set up like this: https://i.sstatic.net/oOqGR.png In one of the views, ther ...

Issue with event.stopPropagation() in Angular 6 directive when using a template-driven form that already takes event.data

I am currently developing a citizenNumber component for use in forms. This component implements ControlValueAccessor to work with ngModel. export class CitizenNumberComponent implements ControlValueAccessor { private _value: string; @Input() place ...

Step-by-step guide on displaying a div once certain input fields are completed

For more information on how this works, you can visit: this link I'm curious about customizing this to work with specific sections of a form rather than the entire form. I've successfully implemented it using IDs only, but not classes. What I ...

Guide on integrating an element into a different element in a Vue 3 Tree Viewer

In my current setup, I've implemented a TreeView component that holds a tree. Each tree entry includes Children with their own unique label, perm, and further children. Take a look at an example of the tree: App.vue let tree = ref({ label: 'o ...

What is the best way to display a landing page using an AngularJS web application?

As a newcomer to AngularJS, I am currently working on a small web application using ui-router for page routing. I have a landing page that consists of static content with clickable links covering the entire screen, while other pages only occupy the "ui-v ...

Exploring the intricacies of Node-Craigslist syntax

Greetings! I am currently utilizing the node-craigslist package found at https://github.com/brozeph/node-craigslist and I am in need of assistance with some syntax related to the details method. The documentation provides the following example: client . ...

Using Angular JS to Implement Multi-filtering for Lists

Having trouble with the filter function in Angular JS when trying to filter a list using different links. I've been struggling to get it right even after trying some examples. Can anyone provide guidance on how to correctly filter the list? HTML < ...

Transform JSON code from JQuery to PHP

Currently, I am in the process of translating a code snippet from JQuery to PHP for performing a json POST request to a remote server. Here is my original Jquery code: $( document ).ready(function() { $('#button').click( function() ...

Modifying background image with Javascript

I've been working on developing a slideshow for one of the web pages I'm building. To achieve this, I set up a div with a unique class name that allows me to change the background image using JavaScript. Here's what I've accomplished so ...

jQuery datatable loses highlight after page refresh

I am currently working with a datatable that utilizes ajax to load data. var table = $('#example').DataTable({ "ajax": "xxxxxx.aspx", stateSave: true, "aLengthMenu": [ [10, 25, 50, 100], [10, 25, 50, 100] ], ...

React frontend encountered a connectivity issue while trying to establish a network connection

Our app utilizes next.js connected to express, which is further linked to AWS MySql for database management. While attempting to load some products stored in the database, an error message pops up: TypeError: NetworkError when trying to fetch resource. ...

Prevent the upward arrow from appearing on the first row and the downward arrow from appearing on the last row when

This is a straightforward question, but I'm unsure how to achieve it. I am currently working on sorting columns using jQuery. $(document).ready(function(){ $(".up,.down,.top,.bottom").click(function(){ var row = $(this).parents("tr:f ...

Express.js session management -- Ensuring sessions are created exclusively for authenticated users

I've implemented the express-session Node module to handle secure session cookies. // To ensure certain requests require an active session, this code sets up a secure session cookie app.use(expressSession({ secret: "wouldn'tyouliketoknow", ...