I am trying to create tables using the v-for directive, but I wanted to know if there is any way to do some conditionals inside the individual tables based on a certain value. I am including a generic version of what I have as my data and what I am trying to produce.
Data Example (this is what I am pulling in from the API call):
MainOrg | SubOrgId | SubOrgName | SubOrgState | TotalOrgs |
---|---|---|---|---|
10110 | 101101 | Main Office | AK | 26 |
10110 | 101102 | Branch Office | AK | 4 |
10110 | 101102 | Sat Office | AK | 2 |
10111 | 101111 | Main Office | FL | 26 |
10111 | 101112 | Branch Office | FL | 4 |
10111 | 101112 | Sat Office | FL | 2 |
I am trying to loop through the "MainOrg" column and create a new table for each unique one, then have the data that corresponds to that "MainOrg" in the output table. The "MainOrg" would become the title for the table.
The output I am trying to get is as follows:
10110
SubOrgId | SubOrgName | SubOrgState | TotalOrgs |
---|---|---|---|
101101 | Main Office | AK | 26 |
101102 | Branch Office | AK | 4 |
101102 | Sat Office | AK | 2 |
10111
SubOrgId | SubOrgName | SubOrgState | TotalOrgs |
---|---|---|---|
101111 | Main Office | FL | 26 |
101112 | Branch Office | FL | 4 |
101112 | Sat Office | FL | 2 |
I have been running into the following issues with the v-for and v-if directives:
**Duplicates main orgs due to it being based on index
<table v-for="(d, index) in data" :key="index">
<thead>
<tr>
<th>{{ d.MainOrg }}</th>
</tr>
</thead>
I really want it to spit out a new table for each unique "MainOrg", then contextually look at my data to include the "SubOrg" data that matches it, per my desired result above. I have not been able to find the right combination of Vue Html and/or JavaScript that can create the desired result based on the need for the data to be separated into individual tables. Also, within the table elements, I am unsure of how to reference the index of the data for conditionals. For example, when I tried using v-if instead of v-for to create the tables by accessing a unique array of the MainOrgs, I did not know how to contextually tie the data together.
In non-programmer speak/pseudo code: Take the unique MainOrg values from data and create a new table for each MainOrg. Then, take the remaining columns/rows from data and add them to each MainOrg table where the row context (data.MainOrg) matches the table for that MainOrg.
Apologies for the long post, but any help is greatly appreciated.
Edit After trying answer below, this is what I have:
computed: {
regions: ({ estabSearchResult }) =>
estabSearchResult.reduce(
(map, { region, estabId, estabName, estabCity, estabState, stateName, estabZip, orgCount}) => ({
...map,
[region]: [...(map[region] ?? []), estabId, estabName, estabCity, estabState, stateName, estabZip, orgCount],
}),
{}
)
},
Which gives me the following:
IN0110:Array[18]
0:"Office - Washington"
1:"Washington"
2:"DC"
3:"District of Columbia"
4:"20240"
5:26
6:"Museum"
7:"Browning"
8:"MT"
9:"Montana"
10:"59417"
11:2
12:"Southern Plains"
13:"Anadarko"
14:"OK"
15:"Oklahoma"
16:"73005"
17:1
this is closer, but there seems to be something else I am missing.
CodePudding user response:
First I think you have to convert your array of objects
into an object of objects
which contains MainOrg
as key with the help of Array.forEach()
Like this :
const tableAllData = [{
MainOrg: 10110,
SubOrgId: 101101,
SubOrgName: 'Main Office'
}, {
MainOrg: 10110,
SubOrgId: 101102,
SubOrgName: 'Branch Office'
},{
MainOrg: 10110,
SubOrgId: 101102,
SubOrgName: 'Sat Office'
}, {
MainOrg: 10111,
SubOrgId: 101111,
SubOrgName: 'Main Office'
},{
MainOrg: 10111,
SubOrgId: 101112,
SubOrgName: 'Branch Office'
}, {
MainOrg: 10111,
SubOrgId: 101112,
SubOrgName: 'Sat Office'
}];
const newObj = {};
tableAllData.forEach(obj => {
newObj[obj.MainOrg] ?
newObj[obj.MainOrg].push(obj) : newObj[obj.MainOrg] = [obj]
});
console.log(newObj);
Live Demo with Vue :
new Vue({
el: '#app',
data: {
tableAllData: [{
MainOrg: 10110,
SubOrgId: 101101,
SubOrgName: 'Main Office'
}, {
MainOrg: 10110,
SubOrgId: 101102,
SubOrgName: 'Branch Office'
},{
MainOrg: 10110,
SubOrgId: 101102,
SubOrgName: 'Sat Office'
}, {
MainOrg: 10111,
SubOrgId: 101111,
SubOrgName: 'Main Office'
},{
MainOrg: 10111,
SubOrgId: 101112,
SubOrgName: 'Branch Office'
}, {
MainOrg: 10111,
SubOrgId: 101112,
SubOrgName: 'Sat Office'
}],
categorizedTable: {}
},
mounted() {
const newObj = {};
this.tableAllData.forEach(obj => {
newObj[obj.MainOrg] ?
newObj[obj.MainOrg].push(obj) : newObj[obj.MainOrg] = [obj]
});
this.categorizedTable = newObj;
}
})
table, thead, th, td, tr {
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="item in Object.keys(categorizedTable)" :key="item">
<h3>{{ item }}</h3>
<table>
<thead>
<th>SubOrgId</th>
<th>SubOrgName</th>
</thead>
<tbody>
<tr v-for="(row, index) in categorizedTable[item]" :key="index">
<td>{{ row.SubOrgId }}</td>
<td>{{ row.SubOrgName }}</td>
</tr>
</tbody>
</table>
</div>
</div>
CodePudding user response:
Create a computed property to represent the new data structure
computed: {
mainOrgs: ({ data }) =>
data.reduce(
(map, { MainOrg, ...rest }) => ({
...map,
[MainOrg]: [...(map[MainOrg] ?? []), rest],
}),
{}
),
};
This looks something like
{
"10110": [{ SubOrgId: 101101, ... }, ...],
"10111": [{ SubOrgId: 101111, ... }, ...],
}
which you can then use in rendering
<div v-for="(orgs, mainOrg) in mainOrgs" :key="mainOrg">
<p><strong>{{ mainOrg }}</strong></p>
<table>
<thead>
<tr>
<th>SubOrgId</th>
<th>SubOrgName</th>
<th>SubOrgState</th>
<th>TotalOrgs</th>
</tr>
</thead>
<tbody>
<tr v-for="org in orgs" :key="org.SubOrgId">
<td>{{ org.SubOrgId }}</td>
<!-- etc -->
</tr>
</tbody>
</table>
</div>