Showing various VueJS data tables using Bootstrap, dependent on API response

Currently, I am utilizing the bootstrap-vue table to display my data. Right now, all of my information is contained in a single table. To provide an example, let's say there are 10 rows in this table. The first 5 rows have the value A in the first column, while the next 5 rows have the value B in the first column.

My goal is to segment this table into two separate tables on the page. The first table should only include rows with the value A, and the second table should consist of rows with the value B. Since I may have numerous unique values like this, ideally I would want individual tables for each value present (e.g., if there are 10 different values, then I would need 10 separate tables). Is it possible to accomplish this?

Alternatively, another approach could be to implement collapsible rows. I don't mean the traditional 'More Details' feature, but rather, a functionality where clicking on a specific value, such as A, would expand all rows with that same value in the original table format.

I initially considered using rows that span columns (Having grouped rows in bootstrap Vue table), but unfortunately, this feature is not supported by the current version of the bootstrap vue-js table.

Answer №1

To achieve this, you can create a computed property that organizes your array into groups.

The computed property will output an object with keys representing the grouping values and corresponding arrays containing items in each group.

/* Sample structure returned by the computed property */
{
  A: [],
  B: [],
  C: []
}

You can then iterate over each key in the groupedItems using a v-for loop.

<!-- 
  groupedItems is the computed property with the above structure.
  It will generate a new table for each type/key in the `groupedItems` object.
-->
<div v-for="(group, type) in groupedItems">
  <b-table :fields="fields" :items="group"><b-table>
</div>

Example snippet:

A simple example showcasing a header indicating the type and a table below it.

/* Generating random example data */
const types = ['A', 'B', 'C']
const items = [];
for(let i = 0; i < 15; i++) {
  items.push({
    type: types[i % 3],
    id: i + 1,
    random: Math.random()
  })
}

new Vue({
  el: '#app',
  computed: {
    groupedItems() {
      const groups = {};
      
      this.items.forEach(item => {
        if(groups[item.type]) {
          groups[item.type].push(item);
        } else {
          groups[item.type] = [item];
        }
      });

      return groups;
    }
  },
  data() {
    return {
      items: items,
      fields: ['type', 'id', 'random']
    }
  }
})
<!-- Bootstrap and BootstrapVue CDN links -->
<link href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue/dist/bootstrap-vue.css" rel="stylesheet" />

<!-- Vue.js script tag -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue/dist/bootstrap-vue.js"></script>


<div id="app">
  <div v-for="(items, type) in groupedItems">
    <h2>Type: {{ type }}</h2>
    <b-table :fields="fields" :items="items">
      <template #cell(type)="{ value }">
        Type: {{ value }}
      </template>
    </b-table>
  </div>
</div>


Accordion Example:

This demo utilizes an accordion to toggle visibility of each group. Only one group can be open at a time, but you can modify it to allow multiple groups at once.

/* Generating random example data */
const types = ['A', 'B', 'C']
const items = [];
for(let i = 0; i < 15; i++) {
  items.push({
    type: types[i % 3],
    id: i + 1,
    random: Math.random()
  })
}

new Vue({
  el: '#app',
  computed: {
    groupedItems() {
      const groups = {};

      this.items.forEach(item => {
        if(groups[item.type]) {
          groups[item.type].push(item);
        } else {
          groups[item.type] = [item];
        }
      });

      return groups;
    }
  },
  data() {
    return {
      items: items,
      fields: ['type', 'id', 'random']
    }
  }
})
<!-- Bootstrap and BootstrapVue CDN links -->
<link href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue/dist/bootstrap-vue.css" rel="stylesheet" />

<!-- Vue.js script tag -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue/dist/bootstrap-vue.js"></script>


<div id="app">
  <b-card no-body class="mb-1" v-for="(group, type) in groupedItems">
    <b-card-header header-tag="header" class="p-0" role="tab">
      <b-button block v-b-toggle="`accordion-${type}`" variant="primary">
        Type {{ type }}
      </b-button>
    </b-card-header>
    <b-collapse :id="`accordion-${type}`" accordion="table-accordion" role="tabpanel">
      <b-table :fields="fields" :items="group"></b-table>
    </b-collapse>
  </b-card>
</div>


Adding Nested Level:

You can extend the nesting further by implementing another level following the same pattern.

/* Generating random example data */
const types = ['A', 'B', 'C']
const items = [];
for(let i = 0; i < 30; i++) {
  items.push({
    type: types[i % 3],
    group: i % 9,
    id: i + 1,
    random: Math.random()
  })
}

new Vue({
  el: '#app',
  computed: {
    groupedItems() {
      const groups = {};

      this.items.forEach(item => {
        if(!groups[item.type]) groups[item.type] = {};

        if(groups[item.type][item.group]) {
          groups[item.type][item.group].push(item);
        } else {
          groups[item.type][item.group] = [item];
        }
      });

      return groups;
    }
  },
  data() {
    return {
      items: items,
      fields: ['type', 'id', 'random']
    }
  }
})
<!-- Bootstrap and BootstrapVue CDN links -->
<link href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue/dist/bootstrap-vue.css" rel="stylesheet" />

<!-- Vue.js script tag -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue/dist/bootstrap-vue.js"></script>


<div id="app">
  <b-card no-body class="mb-4" v-for="(groups, type) in groupedItems">
    <b-card-header header-tag="header" class="p-0" role="tab">
      <b-button block v-b-toggle="`accordion-${type}`" variant="primary">
        Type {{ type }}
      </b-button>
    </b-card-header>
    <b-collapse :id="`accordion-${type}`" visible role="tabpanel">
      <b-card no-body v-for="(items, group) in groups">
        <b-card-header header-tag="header" class="p-0" role="tab">
          <b-button block v-b-toggle="`accordion-group-${group}`" variant="secondary">
            Group {{ group }}
          </b-button>
        </b-card-header>
        <b-collapse :id="`accordion-group-${group}`" :accordion="`table-accordion-${type}`" role="tabpanel">
          <b-table :fields="fields" :items="items"></b-table>
        </b-collapse>
      </b-card>
    </b-collapse>
  </b-card>
</div>

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 steps can I take to minify my code using react-create-app?

Currently, I am facing an issue with minifying my code on the server. Despite running npm run build, which is supposed to handle all the minifying processes (as shown here: https://i.stack.imgur.com/wjpd7.png), I still see the unminified code when accessin ...

When running scripts, Protractor is unable to perform a click action in Safari, even though it works perfectly in

Currently, I am in the process of developing an angular application and utilizing directconnect for Chrome and Firefox. All my test scripts are functioning as expected, however, a new requirement has been introduced to run these same tests on Safari. To ...

What is the functionality of named function expressions?

After coming across an intriguing example in the book labeled as a "named function expression," I was curious to delve into its mechanics. While the authors mentioned it's not commonly seen, I found it fascinating. The process of declaring the functi ...

Is there a way to store an SQL query within a variable and then expand upon it?

While experimenting with potential SQL injections on my database, I've encountered an issue where a simple function returns results that a user should not have access to. The return value seems to be correct based on the id, but the rest of the query ...

Tips on sending AJAX call parameters individually

My JavaScript AJAX method sends parameters to a controller: function selectClass(day) { var section_id = document.getElementById('section_id2').value; var class_id = document.getElementById('class_id').value; alert("day" + ...

Rendering Content Conditionally Using Vue and Prime Vue Component Library

Currently, I have a diagram that consists of inputs and outputs. With the help of Primevue, I am able to render a table with data for either the inputs or outputs individually. However, I need the columns in the table to vary depending on whether it is dis ...

Tips for handling various mandatory fields for two different user roles within a unified userModel.ts file on a Next.js and MongoDB user registration API platform

Could you please review my code and provide any suggestions for improvement? I have two types of user roles, candidate and business, each with multiple unique fields. My goal is to consolidate all these fields into one userModel.ts file. import mongoose ...

Looking for assistance in correctly identifying types in react-leaflet for TypeScript?

Embarking on my 'first' project involving react-scripts-ts and react-leaflet. I am attempting to create a class that should be fairly straightforward: import {map, TileLayer, Popup, Marker } from 'react-leaflet'; class LeafletMap exte ...

What is the best approach for extracting dynamically generated content from this particular website?

Looking to scrape data from this website Attempting to extract "timestamp" using Python and store it in a variable for customized parsing. Tried using scrapy for scraping the "timestamp", but faced limitations due to javascript-generated data not being s ...

What is the best way to invoke an external JavaScript source using another JavaScript source?

I am trying to connect 2 different files together. file1.php and document.html file1.php has the following code in it: document.writeln('< script src="https://www.googletagservices.com/tag/js/gpt.js"> googletag.pubads().definePassback ...

Trigger is not activated by dynamically created element

I am dealing with a block of code that is dynamic and looks like this. var li3 = document.createElement('li'); li3.classList.add("col-sm-3"); li3.classList.add("no_padding"); var inner = ""; inner = inner ...

The synchronization between the First Column Scroll and Table Filter Function is out of alignment

I haven't coded for a while and my knowledge of JavaScript is still in its early stages, so please excuse me if this question seems a bit naive. Essentially, I've created code that filters an HTML table based on the items in the first column. Th ...

Arranging an array of objects from the Fetch API into rows and columns in Bootstrap 4 by utilizing a foreach loop to iterate through the array

I am currently retrieving data from an external API, which returns an array of objects. Each object contains details of characters from the Harry Potter movies, and there are a total of 50 objects in the array. I am using a foreach loop to iterate through ...

What's the best way to utilize Bootstrap 4 flexbox to ensure that a sidebar column menu smoothly transitions into a top column menu when viewed on a mobile device?

I would like the menu to always be displayed as a column, regardless of the screen size. Currently, it switches to a horizontal top layout and then wraps to two rows before becoming a column on smaller screens. I want it to stay as a column at all times an ...

Ways to implement distinct values for model and input field in Angular 5

I'm currently working on an Angular 5 application and I have a requirement to format an input field with thousand separators (spaces). However, the model I am using only allows numbers without spaces. Since my application is already fully developed, ...

I attempted to define a function in order to pass it as props, only to encounter a compilation error

I am currently facing an issue with a React component where I am trying to pass a function to another component. The problem lies in my inability to properly define the function, resulting in a compilation error. export default function App() { createActi ...

Issue with Jquery functionality when Vue component is duplicated in multiple instances

When developing a custom datetime picker component on Vuejs, I encountered an issue where jQuery was only correctly affecting the first instance of the component on a page. The datetime picker component code in VueJs includes: <div class="date-sec ...

Chrome debugging tool does not refresh page source

This issue has been lingering for quite some time and despite similar questions, I have not come across a satisfactory solution. The problem lies in the fact that the SOURCE used to step through the code does not refresh with every page load. Disabling the ...

JavaScript Date displaying the string in the format YYYY/MM/DD HH:MM

I'm struggling to figure out how to format a date and time string like this: "YYYY-MM-DD-HH-MM" Can anyone help me with this? Here is the code I currently have: var x = new Date(); var formattedTimeStamp = x.toString(); Current Output: Tue Oct 3 ...

Ways to incorporate AJAX into a JavaScript function

I'm still learning about Ajax and I have a JavaScript function that retrieves the value selected from a list within an li element. However, every time this function is executed, the page reloads. I want to incorporate Ajax into this function so that t ...