Home > Enterprise >  Trying to get a b-table to handle an array of arrays
Trying to get a b-table to handle an array of arrays

Time:05-11

Here the is the b-table, it will display a column of food(s)

<b-table :fields="Fields" :items="ITEMS">
   <template #cell(food)="data">
        {{data.item.food}}
   </template>
</b-table>


//The column
Fields() {
 return [{key: 'food', label: 'food'}];
}

Currently the data looks something like this:

[
    {
        "food": "taco"
    },
    {
        "food": "burrito"
    }
]

It writes the values all in a single column to the table.

What I need

I need the table to be able to handle data that looks like this

[
    {
        "foods": [
            {
                "food": "taco"
            },
            {
                "food": "burrito"
            }
        ]
    },
    {
        "foods": [
            {
                "food": "soup"
            },
            {
                "food": "rice"
            }
        ]
    }
]


//The column, probably not correct but I'm trying to get it to read every "food" under all "foods"
Fields(){
      return [{key: 'foods.food', label: 'food'}];
},

This would write the data to the table same as before, in one column.

This almost works!


<!-- Everytime a "foods" array is found, loop through all the food items that it holds  -->

<b-table :fields="Fields" :items="ITEMS">
   <template #cell(foods)="data">
      <div v-for="entry in data.item.foods" :key="entry.food">

          <!-- **THIS TEMPLATE DOES NOT WORK, but if it did then it would count as a solution!** -->
          <template #cell(food)="data">
            {{food}}
          </template>


      </div>
   </template>
</b-table>

CodePudding user response:

To get just a single column table with a list of food names, the bootstrap-vue table wants data to look like this...

fields: ['food'],
items: [
  { food: "taco" },
  { food: "soup" },
  // ...
]

And the markup can be as simple as this...

<div>
  <b-table :items="items" :fields="fields"></b-table>
</div>

I think I understand from the OP (thanks for the edits) that the source data looks differently. The job, then, is to transform the source data into what the table needs. This can best be done with a computed prop. The benefit is that the transformation will be cached and it will remain reactive to changes in the source data.

// first the sourceData needs to be gotten somehow, and made available
// to the computed prop, the op doesn't make clear where it comes from
// so say we have as a literal in mounted...
mounted() {
  this.sourceData = [
    { foods: [ { food: "taco"}, { food: "burrito"} ] },
    { foods: [ { food: "soup"}, { food: "rice"} ] },
  ];
},

// this is all you need to turn the data described in the op
// to the data needed by the table
computed: {
  items() {
    return this.sourceData.map(d => d.foods).flat()
  },
}

Here's a demonstration of that computation working

let sourceData = [
  { foods: [ { food: "taco"}, { food: "burrito"} ] },
  { foods: [ { food: "soup"}, { food: "rice"} ] },
];
      
let result = sourceData.map(d => d.foods).flat();
console.log(result)

CodePudding user response:

This would write the data to the table same as before, in one column.

To achieve this, your items array should be a flat array. Hence, you can convert the input array into a flat array first in mounted() life cycle hook and then bind in the <v-table>.

Demo :

window.onload = () => {
  new Vue({
    el: '#app',
    data() {
      return {
        fields: [{key: 'food', label: 'food'}],
        items: [
          {
            "foods": [
              {
                "food": "taco"
              },
              {
                "food": "burrito"
              }
            ]
          },
          {
            "foods": [
              {
                "food": "soup"
              },
              {
                "food": "rice"
              }
            ]
          }
        ]
      }
    },
    mounted() {
      this.items = this.items.map(d => d.foods).flat();
    }
  })
}
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css"/>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css"/>
<div id="app">
      <b-table :items="items" :fields="fields">
      </b-table>
</div>

  • Related