问题
I am in the process of using bootstrap-vue table. Currently, my entire data resides in one table. Let's assume there are 10 rows in this table, and the first 5 rows contain value A in the first column while the next 5 rows contain value B in the first column.
What I want is, instead of having a single table containing complete data, I divide this table, so that on my page will appear two tables. The first table would contain all rows with values A and the second table would contain all rows with values B. In reality, I would have a lot of these unique values, so let's say, if I have 10 such values, I want 10 such individual tables based on these values. Is this possible to do?
Another idea could be, that if above is not possible, can I have collapsible rows? I am not talking about the More Details functionality, but rather, when I click on the A, all rows with value A would appear in the same table each appearing as a row in the table.
I was initially thinking of having rows that can span columns (Having grouped rows in bootstrap Vue table) but unfortunately, that is not supported by bootstrap vue-js table yet.
回答1:
You can do this by utilizing a computed property that splits your array up into groups.
This computed property will return a object, that contains a key which will be the value you're grouping on, and the value will be an array containing all items in that group.
/* Example structure that the computed property will return */
{
A: [],
B: [],
C: []
}
You can then use a v-for to look each key in the groupedItems
<!--
groupedItems is the computed property, containing the structure shown above.
Will create a new table for each type/key in the `groupedItems` property.
-->
<div v-for="(group, type) in groupedItems">
<b-table :fields="fields" :items="group"><b-table>
</div>
Example snippet:
A fairly basic example, which just display a header of the type and the table underneath.
/* Generate some 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']
}
}
})
<link href="https://unpkg.com/bootstrap@4.5.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue@2.15.0/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.15.0/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>
Example utilizing an accordion
This example utilizes an accordion, to allow each group to be opened/closed.
Accoridon's only allow one group to be open at a type. If you don't want this , you can remove accordion="table-accordion" from the b-collapse so multiple can be opened at the same time.
/* Generate some 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']
}
}
})
<link href="https://unpkg.com/bootstrap@4.5.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue@2.15.0/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.15.0/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>
Additional example based on request in comments.
You can easily add another level by doing the same thing again, but nesting it one level deeper.
/* Generate some 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']
}
}
})
<link href="https://unpkg.com/bootstrap@4.5.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue@2.15.0/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.15.0/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">
Type {{ 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>
来源:https://stackoverflow.com/questions/62288939/displaying-multiple-bootstrap-vuejs-tables-based-on-response-from-api