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.

Categories
BootstrapVue

BootstrapVue — Modals

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 components.

Prevent Closing

We can stop a modal from closing with the .preventDefault method.

For instance, we can write:

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

    <b-modal id="modal" @ok="handleOk">
      <div>Hello!</div>
    </b-modal>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    handleOk(bvModalEvt) {
      bvModalEvt.preventDefault();
    }
  }
};
</script>

We have the handleOk method which is set as the value of the ok event handler.

We called prevetnDefault on bvModalEvt , which is the event object for the modal.

Now when we click the OK button, the modal won’t close.

Modal Content

We can add content to a modal.

For instance, we can add tooltips and popovers:

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

    <b-modal id="modal" ok-only>
      <p>
        <b-button v-b-popover="'Popover'" title="Popover">Button</b-button>
      </p>
      <p>
        <a href="#" v-b-tooltip title="Tooltip">Link</a>
        .
      </p>
    </b-modal>
  </div>
</template>

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

We have a modal with a button that has a popover.

We added it with the v-b-popover directive.

The v-b-tooltip lets us add a tooltip.

Styling

We can style models with various props.

We can change the modal size with the size prop.

For instance, we can write:

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

    <b-modal id="modal" size="xl" title="Extra Large Modal">Hello!</b-modal>
  </div>
</template>

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

We have the size prop to change the size of the modal.

It’s responsive so it won’t overflow the screen.

Other values include 'lg' for large and 'sm' for small.

Scrolling Long Content

We can make long content scrollable.

For instance, we can write:

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

    <b-modal id="modal" title=" Modal" scrollable>
      <p class="my-4" v-for="i in 20" :key="i">foo</p>
    </b-modal>
  </div>
</template>

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

We have the scrollable prop on the modal to make it scrollable.

Vertically Centered Modal

We can vertically center our modal with the centered prop.

For example, we can write:

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

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

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

Now we see the modal is vertically centered.

Variants

There are various props to change the styling variant of various parts of the modal.

They are the following:

  • header-bg-variant
  • header-text-variant
  • body-bg-variant
  • body-text-variant
  • footer-bg-variant
  • footer-text-variant

The value can be danger , warning , info , success , dark , light , etc.

For instance, we can write:

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

    <b-modal id="modal" title=" Modal" header-bg-variant="success" body-text-variant="info">
      <p>hello</p>
    </b-modal>
  </div>
</template>

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

Then the title will have a green background and the body text will be green.

Hide the Backdrop

The backdrop of the modal can be hidden.

We just have to add the hide-backdrop prop.

For example, we can write:

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

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

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

We just add it and the background won’t be darkened.

Disable Animation

To disable the modal animation, we can add the no-fade prop to our modal.

For instance, we write:

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

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

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

and we won’t get any animation when we open or close it.

Footer Button Sizing

We can change the footer button sizing with the button-size prop.

The possible values are sm for small or lg for large.

For example, we can write:

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

    <b-modal id="modal" title=" Modal" button-size="sm">
      <p>hello</p>
    </b-modal>
  </div>
</template>

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

We have button-size set to 'sm' , so the buttons are extra small.

Conclusion

There are many customizations we can do with models. We can stop them from closing.