Categories
BootstrapVue

BootstrapVue — Table Customizations

Spread the love

To make good looking Vue apps, we need to style our components.

To make our lives easier, we can use components with styles built-in.

We look at how to customize table contents.

Colgroups

We can group table columns into colgroups.

For example, we can write:

<template>
  <div id="app">
    <b-table :items="items">
      <template v-slot:table-colgroup="scope">
        <col
          v-for="field in scope.fields"
          :key="field.key"
          :style="{ width: field.key === 'firstName' ? '120px' : '180px' }"
        >
      </template>
    </b-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { firstName: "alex", lastName: "green" },
        {
          firstName: "may",
          lastName: "smith"
        },
        { firstName: "james", lastName: "jones" }
      ]
    };
  }
};
</script>

We have the col component that populates the table-colgroup slot to loop through the fields.

This way, we can style each column with the style prop.

Busy State

b-table lets us pass in the busy prop to flag the table if it’s busy.

This way, we can display something if the table is busy.

For example, we can write:

<template>
  <div id="app">
    <b-table :items="items" busy>
      <template v-slot:table-busy>
        <div>
          <b-spinner></b-spinner>
          <strong>Loading...</strong>
        </div>
      </template>
    </b-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { firstName: "alex", lastName: "green" },
        {
          firstName: "may",
          lastName: "smith"
        },
        { firstName: "james", lastName: "jones" }
      ]
    };
  }
};
</script>

We have the busy prop on b-table and populated the table-busy slow with a spinner and the ‘Loading’ text.

Therefore, instead of seeing the table’s content, we’ll see what’s in the slot instead.

Custom Data Rendering

We can render data in a custom way.

For example, we can write:

<template>
  <div id="app">
    <b-table :items="items">
      <template v-slot:cell(firstName)="data">{{ data.value }}</template>

<template v-slot:cell(lastName)="data">
        <b>{{ data.value }}</b>
      </template>
    </b-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { firstName: "alex", lastName: "green" },
        {
          firstName: "may",
          lastName: "smith"
        },
        { firstName: "james", lastName: "jones" }
      ]
    };
  }
};
</script>

We populate the slots for the columns.

The column’s data can be obtained with data .

v-slot:cell(firstName)=”data” gets the firstName property and assigned it to data .

v-slot:cell(lastName)=”data” does the same for lastName .

And the value property has the value of each property.

Therefore, we can render each piece of data our way.

data in the example above has many properties.

index has the row number.

item has the raw record of each entry.

value is the value for the given key.

unformatted has raw values before passing through the formatter function.

field has the normalized field definition object.

detailsShowing is true if the row-details scoped slot is visible.

toggleDetails can be called to toggle the visibility of the row-details scope slot.

rowSelected is true if the row is selected.

selectRow selects the current row when called.

unselectRow unselects the current row when called.

Display Raw HTML

We can display raw HTML.

To do that we just populate the slot with an element that has the v-html directive.

For instance, we can write:

<template>
  <div id="app">
    <b-table :items="items">
      <template v-slot:cell(lastName)="data">
        <span v-html="data.value"></span>
      </template>
    </b-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [{ firstName: "alex", lastName: "<b>green</b>" }]
    };
  }
};
</script>

We have a span that has the v-html directive set to data.value which has our lastName ‘s value.

So the HTML code will be rendered without sanitization.

However, we have to be careful so that we don’t get attacked with cross-site scripting attacks.

Formatter Callback

We can add a formatted to out fields array entries to format our cells.

For instance, we can write:

<template>
  <div id="app">
    <b-table :items="items" :fields="fields"></b-table>
  </div>
</template>
<script>
export default {
  data() {
    return {
      fields: [
        {
          key: "name",
          label: "Full Name",
          formatter: "fullName"
        }
      ],
      items: [
        { firstName: "alex", lastName: "green" },
        {
          firstName: "may",
          lastName: "smith"
        },
        { firstName: "james", lastName: "jones" }
      ]
    };
  },
  methods: {
    fullName(value, key, item) {
      return `${item.firstName} ${item.lastName}`;
    }
  }
};
</script>

We have the fullName method.

It takes the item parameter, which has the object in items , and return the firstName and lastName properties combined together.

The name of it is set as the value of formatter in our field’s array entry.

Therefore, now we have one Full Name column that has both field’s values displayed together.

We can also write:

<template>
  <div id="app">
    <b-table :items="items" :fields="fields"></b-table>
  </div>
</template>
<script>
export default {
  data() {
    return {
      fields: [
        {
          key: "name",
          label: "Full Name",
          formatter(value, key, item) {
            return `${item.firstName} ${item.lastName}`;
          }
        }
      ],
      items: [
        { firstName: "alex", lastName: "green" },
        {
          firstName: "may",
          lastName: "smith"
        },
        { firstName: "james", lastName: "jones" }
      ]
    };
  }
};
</script>

We moved the formatted function to fields entry object instead of having it in methods .

Photo by Marylou Fortier on Unsplash

Conclusion

We can format table cells with formatted functions.

Also, we can customize cell layout and formatting with slots or raw HTML.

We can set the busy state to display something when the table’s data is loading.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *