简体   繁体   中英

Vue V-for in tables

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.

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>

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM