Search code examples
vue-clibootstrap-vue

How to divide a column to have multiple rows in b-table in bootstrap vue?


I am creating SPA using vue. I have JSON array :

[
    {
        date: new Date(2076, 5, 10),
        customer: {id: 0,name: "Foo bar",tol: "Some tol",city: "Some City",},
        items: [
            {code: "gs",name: "Generic Shoes",cost: 500,quantity: 5},
            {code: "nf",name: "North Facing Jacket",cost: 5000,quantity: 5},
            {code: "lp",name: "Lee Vice Jeans Pant",cost: 1500,quantity: 15}
        ],
    }
]

which now contains one object that has date, customer and items primarily. I want to make table that will contain date, customer and items as fields, and each row of table will contain multiple row of items. Something like this :

enter image description here,

This thing has only one row, but as you can imagine there might be multiple row for multiple {date, customer, items[]}.

This was best I was able to do :

<b-container>
    <b-table responsive="true" striped hover :items="DraftList" :fields="fields">
        <template slot="[date]" slot-scope="data">{{data.value|formatDate}}</template>
        <template slot="[customer]" slot-scope="data">{{data.value.name}}</template>
        <template slot="[items]" slot-scope="data">{{data.value}}</template>
    </b-table>
</b-container>
<script>
import { mapState } from "vuex";
export default {
  data() {
    return {
      fields: [
        { key: "date", sortable: true },
        {
          key: "customer",
          label: "Customer's Name",
          sortable: true
        },
        {
          key: "items",
          label: "Item List",
          sortable: true
        }
      ]
    };
  },
  computed: {
    ...mapState(["DraftList"])
  },
  mounted() {},
  filters: {
    formatDate: date => {
      if (date instanceof Date) {
        let month = "" + (date.getMonth() + 1);
        let day = "" + date.getDate();
        let year = date.getFullYear();
        if (month.length < 2) month = "0" + month;
        if (day.length < 2) day = "0" + day;
        return [year, month, day].join("-");
      }
      return null;
    }
  }
};
</script>

I am stuck, what should I do now? I cannot properly term my searches either.


Solution

  • Solved it using v-for and rowspan

    <b-table-simple responsive="true" hover outlined>
        <colgroup>
            <col />
            <col />
        </colgroup>
        <colgroup>
            <col />
            <col />
            <col />
        </colgroup>
        <colgroup>
            <col />
            <col />
        </colgroup>
        <b-thead head-variant="light">
            <b-tr>
                <b-th rowspan="2">Date</b-th>
                <b-th rowspan="2">Customer's Name</b-th>
                <b-th colspan="4">Items</b-th>
            </b-tr>
            <b-tr>
                <b-th>code</b-th>
                <b-th>Name</b-th>
                <b-th>Cost</b-th>
                <b-th>Quantity</b-th>
            </b-tr>
        </b-thead>
        <b-tbody v-for="(draft,index) in DraftList" :key="index">
            <b-tr>
                <b-td :rowspan="draft.items.length+1">{{draft.date|formatDate}}</b-td>
                <b-td :rowspan="draft.items.length+1">{{draft.customer.name}}</b-td>
            </b-tr>
            <b-tr v-for="(item, itemIndex) in draft.items" :key="itemIndex">
                <b-td>{{item.code}}</b-td>
                <b-td>{{item.name}}</b-td>
                <b-td>{{item.cost}}</b-td>
                <b-td>{{item.quantity}}</b-td>
            </b-tr>
        </b-tbody>
    </b-table-simple>