Categories
BootstrapVue

BootstrapVue — Custom Tables

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 customizing tables.

Fields

We can add a fields prop to specify how we want to display the fields.

For example, we can write:

<template>
  <div id="app">
    <b-table striped hover :items="items" :fields="fields"></b-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      fields: [
        {
          key: "lastName",
          sortable: true,
          label: "Last"
        },
        {
          key: "firstName",
          sortable: false,
          label: "First"
        }
      ],
      items: [
        { firstName: "alex", lastName: "green" },
        {
          firstName: "may",
          lastName: "smith"
        },
        { firstName: "james", lastName: "jones" }
      ]
    };
  }
};
</script>

We have the fields array with the label to display.

label is what we display nd key ios the property name of the entry to display.

Styling

There are many props we can add to b-table for styling.

striped makes the row striped.

border makes the table bordered.

borderless makes the table borderless.

outlined adds a thin border on all sides of the table.

small makes tables more compact by cutting cell padding in half.

hover enables hover highlighting on table rows.

dark inverts the color.

fixed makes the columns fixed width.

responsives makes the table responsive by letting it scroll horizontally.

sticky-header makes the header sticky.

stacked makes a responsive stacked table.

caption-top lets us add a caption above the table.

table-variant gives the table a theme color variant.

head-variant use 'light' or 'dark' to make the table header appear light or dark gray respectively.

foot-variant turns on the table footer with the same contents as the table header.

foot-clone turns on the table footer with the same contents as the table header.

no-footer-sorting disables sorting icons and clicks.

no-border-collapse disables collapsing of table borders.

For example, we can write:

<template>
  <div id="app">
    <b-table striped hover :items="items" borderless small></b-table>
  </div>
</template>

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

to shrink the cells and make the table borderless with the small and borderless props respectively.

We also have striped to make the table rows alternate in color.

hover makes the row highlight when it’s hovered.

Responsive Tables

We can add the responsive prop to make the table responsive.

For instance, we can write:

<template>
  <div id="app">
    <b-table :items="items" responsive></b-table>
  </div>
</template>

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

Then when the screen is narrow, the table can be scrolled horizontally to see all the content.

Stacked Tables

Stacked tables are tables that can be rendered in a visually stacked format.

We can do that across all viewports by setting the stacked prop to true .

Or we can do it for specific breakpoints like sm , md , lg , or xl .

For instance, we can write:

<template>
  <div id="app">
    <b-table :items="items" stacked="md"></b-table>
  </div>
</template>

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

and make it stacked only when the screen is less than 768px wide.

When a table is stacked, the content can’t be sorted by clicking the field labels.

top-row and bottom-row slots will also be hidden.

Always stacked tables won’t have the table header, footer, top, and bottom row slots won’t be rendered.

Table Caption

To add a caption to our table, we can add the caption prop.

For example, we can write:

<template>
  <div id="app">
    <b-table :items="items" >
      <template v-slot:table-caption>table of names</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 table-caption slot with our content.

Conclusion

There are many props to let us style tables the way we like.

Also, we can create responsive or stacked tables to make tables look good on any screen.

Categories
BootstrapVue

BootstrapVue — Simple Tables

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 by using the b-table-simple component.

Simple Tables

The b-table-simple component lets us create a table as we do in regular HTML.

Therefore, we have full control of each cell.

We can add the striped , bordered , borderless , outlined , small , hover , dark , fixed , responsive , and sticky-header props to style the table the way we like.

For example, we can create one by writing:

<template>
  <div id="app">
    <b-table-simple responsive>
      <b-thead>
        <b-tr>
          <b-th>id</b-th>
          <b-th>first</b-th>
          <b-th>last</b-th>
        </b-tr>
      </b-thead>
      <b-tbody>
        <b-tr v-for="i of items" :key="i.id">
          <b-td>{{i.id}}</b-td>
          <b-td>{{i.firstName}}</b-td>
          <b-td>{{i.lastName}}</b-td>
        </b-tr>
      </b-tbody>
    </b-table-simple>
  </div>
</template>

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

We have the b-table-simple component.

Inside it, we have the b-thead component to add the table header.

b-tr add the rows.

b-th add the header cells.

b-tbody adds the table body.

And b-td adds the body cells.

Simple tables can be stacked like regular tables.

For example, we can write:

<template>
  <div id="app">
    <b-table-simple stacked>
      <b-tbody>
        <b-tr v-for="i of items" :key="i.id">
          <b-td stacked-heading="id">{{i.id}}</b-td>
          <b-td stacked-heading="first">{{i.firstName}}</b-td>
          <b-td stacked-heading="last">{{i.lastName}}</b-td>
        </b-tr>
      </b-tbody>
    </b-table-simple>
  </div>
</template>

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

We have the stacked prop with the stacked-heading on each table cell to specify the field name to display.

Simple Tables and Sticky Columns

We can make a column sticky with the sticky-column prop.

For instance, we can write:

<template>
  <div id="app">
    <b-table-simple responsive>
      <b-thead>
        <b-tr>
          <b-th sticky-column>id</b-th>
          <b-th>first</b-th>
          <b-th>last</b-th>
        </b-tr>
      </b-thead>
      <b-tbody>
        <b-tr v-for="i of items" :key="i.id">
          <b-td sticky-column>{{i.id}}</b-td>
          <b-td>{{i.firstName}}</b-td>
          <b-td>{{i.lastName}}</b-td>
        </b-tr>
      </b-tbody>
    </b-table-simple>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      items: [
        { id: 1, firstName: "alex", lastName: "green" },
        {
          id: 2,
          firstName: "may",
          lastName: "smith"
        },
        { id: 3, firstName: "james", lastName: "jones" }
      ]
    };
  }
};
</script>

We just put the sticky-column prop on the column cells to make the column sticky.

Helper Components

Helper components are added to tables to let us render things in a custom manner.

b-table-simple can include b-tbody , b-thead , b-tfoot , b-te , b-td , and b-th components.

b-table can only include b-tr , b-td , and b-th components.

Conclusion

We can use the b-table-simple component to let us create tables in a more flexible manner.

Also, we can add sticky columns into our table

They can be also be shown as a stacked table.

Categories
BootstrapVue

BootstrapVue — Customizing Spinner and Basic Tables

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 spinners and add basic tables.

Aligning Spinners

We can add classes or alignment.

For instance, we can write:

<template>
  <div id="app">
    <b-spinner class="m-5"></b-spinner>
  </div>
</template>

<script>
export default {};
</script>

to add the m-5 class to add some margins around the spinner.

Placement

The placement of the spinner can be changed.

For example, we can write:

<template>
  <div id="app">
    <div class="d-flex align-items-center">
      <b-spinner></b-spinner>
    </div>
  </div>
</template>

<script>
export default {};
</script>

to center align the spinner.

Floats

We can apply the float classes that come with Bootstrap to put the spinner left or right.

So we can write:

<template>
  <div id="app">
    <div class="clearfix">
      <b-spinner class="float-right"></b-spinner>
    </div>
  </div>
</template>

<script>
export default {};
</script>

to use the clearfix class so that we can float the spinner to the right.

Text Align

We can use the text-center class to align the spinner to the center of the page:

<template>
  <div id="app">
    <div class="text-center">
      <b-spinner></b-spinner>
    </div>
  </div>
</template>

<script>
export default {};
</script>

Spinners in Buttons

We can put spinners in buttons.

For example, we can write:

<template>
  <div id="app">
    <b-button variant="primary" disabled>
      <b-spinner small></b-spinner>Loading...
    </b-button>
  </div>
</template>

<script>
export default {};
</script>

We have the spinner inside a button along with some text.

Tables

BootstrapVue comes with the b-table component to let us display tables.

There are 2 lighter weight alternatives, which are b-table-lite and b-table-simple .

For example, we can write:

<template>
  <div id="app">
    <b-table striped hover :items="items"></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 items prop that takes an array of objects to render into a table.

striped makes the rows alternate in color.

hover makes the rows highlight when it’s hovered.

The property names are automatically mapped to individual words and capitalize each word.

This conversion is done for kebab case, snake case, or camelCase property names.

We can add the _rowVariant or _cellVariant properties to change the styles of various cells.

For example, we can write:

<template>
  <div id="app">
    <b-table striped hover :items="items"></b-table>
  </div>
</template>

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

_rowVariant makes the whole row the same color.

'success' makes the background green

_cellVariants makes individual cells a different color.

So lastName is light blue since it hs variant 'info' .

And firstName ‘s variant is 'warning' so it’s yellow.

The _cellVariants and _rowVariants only applies to the entry that they are in.

Fields

We can specify how the fields are displayed explicitly.

b-table can take a fields prop with an array of field to display.

For example, we can write:

<template>
  <div id="app">
    <b-table striped hover :items="items" :fields='fields'></b-table>
  </div>
</template>

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

Since fields is [“firstName”] , only the First Name column is displayed.

Fields as an Array of Objects

We can have an array of objects for the fields array.

For example, we can write:

<template>
  <div id="app">
    <b-table striped hover :items="items" :fields="fields"></b-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      fields: [
        {
          key: "lastName",
          sortable: true
        },
        {
          key: "firstName",
          sortable: false,
          variant: "success"
        }
      ],
      items: [
        { firstName: "alex", lastName: "green" },
        {
          firstName: "may",
          lastName: "smith"
        },
        { firstName: "james", lastName: "jones" }
      ]
    };
  }
};
</script>

We have the fields array with the entries being key , sortable , and variant .

key is the property name of the items entries.

variant is the styling variant like primary or success ,

sortable indicates whether the column is sortable.

Therefore, the Last Column is sortable and First Name is not.

Conclusion

We can style and place spinners the way we like with some classes.

Also, we can create simple tables by passing in a few arrays as props into the b-table component.

Categories
BootstrapVue

BootstrapVue — Pagination Nav

l)

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 add pagination nav links to our page.

Page Number Generation

We can generate links with any content we like.

All we have to do is to change he link-gen prop to return the URL path we want.

The page-gen prop can generate any link text we want:

<template>
  <div class="overflow-auto">
    <b-pagination-nav :link-gen="linkGen" :page-gen="pageGen" :number-of-pages="links.length"></b-pagination-nav>
  </div>
</template>

<script>
export default {
  data() {
    return {
      links: ["#foo", "#bar", "#baz", "#qux"]
    };
  },
  methods: {
    linkGen(pageNum) {
      return this.links[pageNum - 1];
    },
    pageGen(pageNum) {
      return this.links[pageNum - 1].slice(1);
    }
  }
};
</script>

We have the linkGen method to return the path that we want. And the pageGen method returns the same entry as linkGen but without the hash.

So we’ll see ‘foo’, ‘bar’, ‘baz’, ‘qux’ are displayed.

And when we click on them, then we go to those links.

Array of Pages

We can use the use-router prop, then the links won’t be a tags. Navigation will be done with JavaScript instead of regular links.

For example, we can write:

<template>
  <div>
    <b-pagination-nav :pages="pages" use-router></b-pagination-nav>
  </div>
</template>

<script>
export default {
  data() {
    return {
      pages: ["?page=1", "?page=2", "?page=3"]
    };
  }
};
</script>

Then we get 3 links with the query strings in pages as the URLs to go to.

We can also have objects in the array with the link and text properties.

For example, we can write:

<template>
  <div>
    <b-pagination-nav :pages="pages" use-router></b-pagination-nav>
  </div>
</template>

<script>
export default {
  data() {
    return {
      pages: [
        { link: "?page=1", text: "one" },
        { link: "?page=2", text: "two" },
        { link: "?page=3", text: "three" }
      ]
    };
  }
};
</script>

We have the link property with the URL to go to.

text has the text for each link.

Alternatively, we can write the query string with the query property instead.

For example, we can write:

<template>
  <div>
    <b-pagination-nav :pages="pages" use-router></b-pagination-nav>
  </div>
</template>

<script>
export default {
  data() {
    return {
      pages: [
        { link: { query: { page: 1 } }, text: "one" },
        { link: { query: { page: 2 } }, text: "two" },
        { link: { query: { page: 3 } }, text: "three" }
      ]
    };
  }
};
</script>

We have the same query string as before.

But creating the query strings is much easier since we can just add key-value pairs.

Button Content

We can change the button contents the way we want.

To do that, we can set the first-text , prev-text , next-text , and last-next props.

For example, we can write:

<template>
  <div>
    <b-pagination-nav
      number-of-pages="15"
      base-url="#"
      first-text="First"
      prev-text="Prev"
      next-text="Next"
      last-text="Last"
    ></b-pagination-nav>
  </div>
</template>

<script>
export default {};
</script>

We set the first-text prop to set the text for going to the first page.

The prev-text prop is set to change the text of the link to go to the previous page.

The next-text prop is set to change the text for the next button.

last-text is used to set the text for the link that goes to the last page.

Also, we can populate the slots for more customization.

For instance, we can write:

<template>
  <div>
    <b-pagination-nav number-of-pages="15" base-url="#">
      <template v-slot:first-text>
        <span class="text-success">First</span>
      </template>
      <template v-slot:prev-text>
        <span class="text-success">Prev</span>
      </template>
      <template v-slot:next-text>
        <span class="text-success">Next</span>
      </template>
      <template v-slot:last-text>
        <span class="text-success">Last</span>
      </template>
      <template v-slot:ellipsis-text>
        <b-spinner small type="grow"></b-spinner>
        <b-spinner small type="grow"></b-spinner>
      </template>
      <template v-slot:page="{ page, active }">
        <b v-if="active">{{ page }}</b>
        <span v-else>{{ page }}</span>
      </template>
    </b-pagination-nav>
  </div>
</template>

<script>
export default {};
</script>

We populate the slots to make the content look our way.

We set the first-text slot to set the text for going to the first page.

The prev-text slot is set to change the text of the link to go to the previous page.

The next-text slot is set to change the text for the next button.

last-text is used to set the text for the link that goes to the last page.

ellipsis-text slot is used to change the ellipsis content.

We changed it to flashing dots.

page has the current page and active indicates if the page is active.

Conclusion

We can customize pagination nav buttons with our own content.

Also, we can customize the paths or query string that the links go to the way we like.

Categories
BootstrapVue

BootstrapVue — Modals and Dialogs

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.

In this article, we’ll look at how to use modal and dialog components.

Disable Footer Buttons

We can disable footer buttons with the cancel-disabled and ok-disabled props.

They disable the cancel and OK buttons respectively.

We can disable both at the same time with the busy prop.

So if we have:

<template>
  <div id="app">
    <b-button v-b-modal.modal>Open</b-button>

    <b-modal id="modal" title=" Modal" busy>
      <p>hello</p>
    </b-modal>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

Then both buttons will be grayed out.

Custom Rendering with Slots

We can customize the render of our modal parts with slots.

The header can be customized by populating the header slot.

The body can be customized by populating the default slot.

And the footer can be customized by populating the footer slot.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-modal.modal>Open</b-button>

    <b-modal id="modal" title=" Modal" busy>
      <template v-slot:modal-header="{ close }">
        <b-button @click="close()">Close Modal</b-button>
        <h5>Header</h5>
      </template>

      <template v-slot:default="{ hide }">
        <p>Body</p>
        <b-button @click="hide()">Hide</b-button>
      </template>

      <template v-slot:modal-footer="{ ok, cancel, hide }">
        <p>Footer</p>
        <b-button @click="ok()">OK</b-button>
        <b-button @click="cancel()">Cancel</b-button>
        <b-button @click="hide('hide')">Hide</b-button>
      </template>
    </b-modal>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

The slots provide us with the methods we can call with each section.

The close method closes the modal in the header.

hide hides the modal in the body.

The footer has the ok , cancel , and hide methods to close the modal.

Multiple Modals

We can have multiple models on one page.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-modal.modal-1>Open First Modal</b-button>

    <b-modal id="modal-1" size="lg" title="First Modal" ok-only no-stacking>
      <p>First</p>
      <b-button v-b-modal.modal-2>Open Second Modal</b-button>
    </b-modal>

    <b-modal id="modal-2" title="Second Modal" ok-only>
      <p class="my-2">Second</p>
      <b-button v-b-modal.modal-3>Open Third Modal</b-button>
    </b-modal>

    <b-modal id="modal-3" title="Third Modal" ok-only>
      <p class="my-1">Third</p>
    </b-modal>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

We have 3 modals which are opened one after the other.

When we click Open First Modal, we open the first modal.

It has an Open Second Modal button to open the second modal.

That modal has the Open Third Modal button to open the 3rd modal.

When we close the top one, the rest are closed.

Modal Message Boxes

We can create simple message boxes with the msgBoxOk and msgBoxConfirm methods.

For example, we can write:

<template>
  <div id="app">
    <b-button @click='openMsgBox'>Open Message Box</b-button>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    async openMsgBox(){
      const value  = await this.$bvModal.msgBoxOk('hello')
      console.log(value);
    }
  }
};
</script>

We added a button to call the openMsgBox method.

It opens a message box with the word 'hello' in it from the string we pass on.

It returns a promise.

When we close it, it’ll resolve to true when we close it.

Also, we can pass in an object with some options as the 2nd argument.

For example, we can write:

<template>
  <div id="app">
    <b-button @click="openMsgBox">Open Message Box</b-button>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    async openMsgBox() {
      const value = await this.$bvModal.msgBoxOk("hello", {
        title: "Confirmation",
        size: "sm",
        buttonSize: "sm",
        okVariant: "success",
        headerClass: "p-2 border-bottom-0",
        footerClass: "p-2 border-top-0",
        centered: true
      });
      console.log(value);
    }
  }
};
</script>

We added a title to the title property.

size sets the size of the modal.

buttonSize sets the button size.

okVariant sets the style of the OK button.

headerClass sets the header’s class.

footerClass sets the footer’s class.

centered makes the modal vertically centered.

Confirm Dialog

The confirm dialog is similar except that it also has a cancel button.

We call the msgBoxConfirm method instead msgBoxOk to open a confirm dialog.

For instance, we can write:

<template>
  <div id="app">
    <b-button @click="openMsgBox">Open Confirm Box</b-button>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    async openMsgBox() {
      const value = await this.$bvModal.msgBoxConfirm("hello", {
        title: "Confirmation",
        size: "sm",
        buttonSize: "sm",
        okVariant: "danger",
        okTitle: "YES",
        cancelTitle: "NO",
        footerClass: "p-2",
        hideHeaderClose: false,
        centered: true
      });
      console.log(value);
    }
  }
};
</script>

We added the okTitle and cancelTitle properties to the options.

When we click the cancel button, the promise will resolve to false .

If we click the ‘x’ on the top right, it’ll resolve to null .

If we click the OK button, it’ll resolve to true .

Conclusion

We can customize the rendering of the modal by populating slots.

Also, we can display simple dialog boxes that returns a promise.

It resolves to different values depending on what is done to close it.