deymbwoi
deymbwoi

Reputation: 135

Vuetify - How do I make the header of v-data-table dynamic

Suppose I have a dynamic array of object which suppose to look like this :

[{id: 1, item: 'apple', taste:'good', item2: 'papaya', taste2: 'bad'}
 {id: 2, item: 'melon', taste: 'bad'},
 {id: 3, item: 'orange', taste: 'good', item2: 'banana', taste2: 'bad', item3: 'grape', taste3:'good'} .......]

How do I make the v-data-table to make the header look like this

ID | ITEM | TASTE | ITEM2 | TASTE2 | ITEM3 | TASTE3 .....

Upvotes: 1

Views: 3989

Answers (2)

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

The headers value should be a computed property which has the following code :

computed: {
        headers() {
          //set having unique values
          let s = new Set();

          this.items.forEach(item => {
            for (f in item) {
              //adding an existing value doesn't override the old one
              s.add(f)
            }
          });
              //respect the headers format required by Vuetify which 
              // should has at least two fields (text, value)
          return Array.from(s).map(a => {
            return {
              text: a.toUpperCase(),
              value: a
            }
          });

        }

      }

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data() {
    return {
      items: [{
          id: 1,
          item: 'apple',
          taste: 'good',
          item2: 'papaya',
          taste2: 'bad'
        }, {
          id: 2,
          item: 'melon',
          taste: 'bad'
        },
        {
          id: 3,
          item: 'orange',
          taste: 'good',
          item2: 'banana',
          taste2: 'bad',
          item3: 'grape',
          taste3: 'good'
        }
      ]
    }
  },
  computed: {
    headers() {
      let s = new Set();

      this.items.forEach(item => {
        for (f in item) {
          s.add(f)
        }
      });

      return Array.from(s).map(a => {
        return {
          text: a.toUpperCase(),
          value: a
        }
      });

    }

  }
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>

<div id="app">
  <v-app>
    <v-content>
      <v-container>
        <v-data-table :headers="headers" :items="items"></v-data-table>
      </v-container>
    </v-content>
  </v-app>
</div>

Upvotes: 4

norbitrial
norbitrial

Reputation: 15166

Using .reduce(), Set() and Object.keys() combination you can get the header as expected.

Try the following:

const data = [
  {id: 1, item: 'apple', taste:'good', item2: 'papaya', taste2: 'bad'},
  {id: 2, item: 'melon', taste: 'bad'},
  {id: 3, item: 'orange', taste: 'good', item2: 'banana', taste2: 'bad', item3: 'grape', taste3:'good'}
];
 
const uniqueKeys = Array.from(data.reduce((a, c) => {
  Object.keys(c).forEach(e => a.add(e));
  return a;
}, new Set()));

console.log(uniqueKeys);

Upvotes: 2

Related Questions