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.

Categories
BootstrapVue

BootstrapVue — Customizing Pagination

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

First and Last Button Type

We can change which buttons are shown in our pagination component.

The first-number prop indicates whether we want to always show the button for the first page.

Likewise, the last-number prop indicates whether we want to always show the button for the last page.

For example, we can write:

<template>
  <div id="app">
    <b-pagination first-number v-model="page" :total-rows="rows" :per-page="perPage"></b-pagination>

    <p>Current Page: {{ page }}</p>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      rows: 100,
      perPage: 10,
      page: 1
    };
  }
};
</script>

Now we always see the button for going to the first page.

Likewise, if we have:

<template>
  <div id="app">
    <b-pagination last-number v-model="page" :total-rows="rows" :per-page="perPage"></b-pagination>

<p>Current Page: {{ page }}</p>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      rows: 100,
      perPage: 10,
      page: 1
    };
  }
};
</script>

Then we always see the button for going to the last page.

Button Size

The button size can be changed with the size prop.

The value sm makes them smaller than the default.

lg makes them larger than the default.

For example, we can write:

<template>
  <div id="app">
    <b-pagination size="sm" v-model="page" :total-rows="rows" :per-page="perPage"></b-pagination>

<p>Current Page: {{ page }}</p>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      rows: 100,
      perPage: 10,
      page: 1
    };
  }
};
</script>

Now they look smaller.

Pill Style

We can add the pills prop to make the buttons look like pills:

<template>
  <div id="app">
    <b-pagination pills v-model="page" :total-rows="rows" :per-page="perPage"></b-pagination>

    <p>Current Page: {{ page }}</p>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      rows: 100,
      perPage: 10,
      page: 1
    };
  }
};
</script>

Alignment

The pagination buttons can be aligned in the position we want.

We can use the align prop to set the alignment.

The default alignment is left.

Other possible values are right to right-align, center for center align, and fill to fill the screen’s width.

For example, we can write:

<template>
  <div id="app">
    <b-pagination align="center" v-model="page" :total-rows="rows" :per-page="perPage"></b-pagination>

<p>Current Page: {{ page }}</p>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      rows: 100,
      perPage: 10,
      page: 1
    };
  }
};
</script>

Since we set align to 'center' , we have the pagination bar at the center of the screen.

Pagination Navigation

BootstrapVue also provides the b-pagination-nav component that lets us set the navigation position.

For instance, we can write:

<template>
  <div id="app">
    <b-pagination-nav :link-gen="linkGen" :number-of-pages="10" use-router></b-pagination-nav>
  </div>
</template>
<script>
export default {
  name: "App",
  methods: {
    linkGen(pageNum) {
      return pageNum === 1 ? "?" : `?page=${pageNum}`;
    }
  }
};
</script>

The difference between b-pagination and b-pagination-nav is that the pagination links can go to the URL that we want.

We have the link-gen prop which returns something that we can append to the current URL.

number-of-page lets us display the number of page buttons that we want.

use-router lets us navigate to URL generated by the Vue or Nuxt router.

The linkGen method can also return an object.

For instance, we can write:

<template>
  <div id="app">
    <b-pagination-nav :link-gen="linkGen" :number-of-pages="10" use-router></b-pagination-nav>
  </div>
</template>
<script>
export default {
  name: "App",
  methods: {
    linkGen(pageNum) {
      return { path: `/foo/page/${pageNum}` };
    }
  }
};
</script>

The object has the have the path property which is appended to the current URL.

It can also have the name and query properties for the route name and the query string respectively:

<template>
  <div id="app">
    <b-pagination-nav :link-gen="linkGen" :number-of-pages="10" use-router></b-pagination-nav>
  </div>
</template>
<script>
export default {
  name: "App",
  methods: {
    linkGen(pageNum) {
      return {
        name: "page",
        params: { page: pageNum }
      };
    }
  }
};
</script>

or:

linkGen(pageNum) {
  return {
    path: '/foo/',
    query: { page: pageNum }
  }
}

Conclusion

We can customize the pagination buttons on the b-pagination component.

Also, we can add a b-pagination-nav to generate links that we can click to go to a URL.

Categories
BootstrapVue

BootstrapVue — Toasts, Alerts, and Tooltips

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 look at how to customize toasts.

We also look at how to add alerts and tooltips.

Toaster Target

We can change the placement of the toasts.

We can set the toaster property to change the placement of a toast.

The following are the possible values of this property:

  • b-toaster-top-right
  • b-toaster-top-left
  • b-toaster-top-center
  • b-toaster-top-full
  • b-toaster-bottom-right
  • b-toaster-bottom-left
  • b-toaster-bottom-center
  • b-toaster-bottom-full

For example, we can write:

<template>
  <div id="app">
    <b-button @click="makeToast()">Show toast</b-button>
  </div>
</template>
<script>
export default {
  name: "App",
  methods: {
    makeToast() {
      this.$bvToast.toast(`hello`, {
        title: "toast",
        autoHideDelay: 5000,
        toaster: "b-toaster-bottom-right"
      });
    }
  }
};
</script>

We changed toaster to “b-toaster-bottom-right” , so the toast will be displayed on the bottom right.

Prepend or Append

We can set the append-toast prop of b-toast to true to append the toast.

Auto-Hide

To disable auto-hide of a toast, we can set no-auto-hide to true .

Links

We can create toasts with a link.

To do that, we set the href property.

For example, we can write:

<template>
  <div id="app">
    <b-button [@click](http://twitter.com/click "Twitter profile for @click")="makeToast()">Show toast</b-button>
  </div>
</template>
<script>
export default {
  name: "App",
  methods: {
    makeToast() {
      this.$bvToast.toast(`hello`, {
        title: "toast",
        autoHideDelay: 5000,
        href: 'http://example.com'
      });
    }
  }
};
</script>

We have the href property that makes the content a link.

So ‘hello’ will be a link.

b-toast

To add our content to a toast more easily, we can use the b-toast component.

To populate the title, we can populate the toast-title slot.

For example, we can write:

<template>
  <div id="app">
    <b-button @click="$bvToast.show('toast')">Show toast</b-button>

    <b-toast id="toast">
      <template v-slot:toast-title>
        <div>
          <b-img blank blank-color="#ff5555" class="mr-2" width="12" height="12"></b-img>title
        </div>
      </template>
      <p>content</p>
    </b-toast>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

We create a toast with the b-toast component.

To show the toast, we added a button.

The $bvToast.show(‘toast’) method call is called with the ID of the toast.

This way, the toast can be opened.

Within the toast-title slot, we have the b-img component to display an image.

We also have the content below it.

Now we get a toast that has images in it.

The default slot has the toast body and consists of anything that’s outside the other slots.

Alerts versus Toasts

We can use the b-alert component to show a simple alert.

For example, we can write:

<template>
  <div id="app">
    <b-button @click="show = !show">Show Alert</b-button>

    <b-alert
      v-model="show"
      class="position-fixed"
      style="z-index: 2000;"
      variant="warning"
      dismissible
    >alert!</b-alert>
  </div>
</template>
<script>
export default {
  name: "App",
  data() {
    return {
      show: false
    };
  }
};
</script>

The b-alert takes a v-model to determine when it’s shown.

If show is true then the alert will be shown.

class is the CSS classes to apply.

style is the style to apply.

dismissible lets us close the alert with a close button.

variant lets us change the style variant.

Tooltips

We can add tooltip elements or components with the b-tooltip component.

Also, we can use the v-b-tooltip directive to add a tooltip.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-tooltip.hover title="Tooltip">Hover Me</b-button>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

We added the v-b-tooltip directive with the hover modifier.

hover means the tooltip is shown on hover.

The title is the title of the tooltip.

Alternatively, we can write:

<template>
  <div id="app">
    <b-button id="tooltip">Hover Me</b-button>
    <b-tooltip target="tooltip" triggers="hover">tooltip</b-tooltip>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

We set the ID of the button to tooltip , which matches the value of target .

This way, it can be opened.

triggers lets us set which even triggers the tooltip.

Then we get the same result as the previous example.

Conclusion

We can add a tooltip with the v-b-tooltip directive or the b-tooltip component.

Alerts are simpler toasts that can’t have as much custom content.

Toasts can be opened in different positions of the page.

Categories
BootstrapVue

BootstrapVue — Table Filtering and Loading

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, including filtering.

Filtering

BootstrapVue table contents can be filtered.

To add built-in filtering features, we can add the filter prop.

For example, we can write:

<template>
  <div id="app">
    <b-table :items="items" filter="may"></b-table>
  </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 pass in a string into the filter prop and it’ll find the rows with the word 'may' in it by searching all properties.

Also, we can pass in a regex to filter by a pattern.

Pagination

We can use the b-pagination component with b-table to control pagination.

For example, we can write:

<template>
  <div id="app">
    <b-table :items="items" :per-page="perPage" :current-page="currentPage"></b-table>
    <b-pagination v-model="currentPage" :total-rows="items.length" :per-page="perPage"></b-pagination>
  </div>
</template>

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

We set the per-page and current-page props to perPage and currentPage respectively.

perPage is fixed to 2.

currentPage is updated when we click on the button rendered by b-pagination .

b-pagination also has the total-rows prop so that it can render the right number of buttons.

v-model is bound to currentPage so that it’s updated when we click the buttons.

Now we get pagination in our table.

Items Provider Functions

We can add an items provider function to provide items.

It can be synchronous or async.

For example, we can make a synchronous one by writing:

function provider() {
  let items = [];
  return items || [];
}

To make an async provider function, we can write:

function provider(ctx, callback) {
  this.fetchData(`/some/url?page=${ctx.currentPage}`)
    .then(data => {
      const items = data.items;
      callback(items)
    })
    .catch(() => {
      callback([])
    })
  return null
}

We return null or undefined to tell b-table that a callback is being used.

The data that we use to fetch the data is in the ctx parameter.

ctx comes from the props.

callback is called with the fetched items to display it with b-table .

We can also use an async function:

async function provider(ctx) {
  try {
    const response = await axios.get(`/some/url?page=${ctx.currentPage}`)
    return response.items;
  } catch (error) {
    return []
  }
}

They can be set as the value of the items prop:

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

<script>
export default {
  name: "App",
  data() {
    return {

};
  },
  methods: {
    provider(){
      return [
        { id: 1, firstName: "alex", lastName: "green" },
        {
          id: 2,
          firstName: "may",
          lastName: "smith"
        },
        { id: 3, firstName: "james", lastName: "jones" }
      ]
    }
  }
};
</script>

Refresh Table Data

We can force the refresh of data table by emitting the bv::refresh::table event.

For example, we can write:

this.$root.$emit('bv::refresh::table', 'table')

to refresh the table with ref table .

Also, we can write:

this.$refs.table.refresh()

Detection of Sorting Change

The b-table component can handle the sort-changed event if we set an event handler for it.

For example, we can write:

<b-table @sort-changed="sortingChanged" ... ></b-table>

Then we can write:

export default {
  methods: {
    sortingChanged(ctx) {
      // ...
    }
  }
}

The ctx parameter is an object with the sortBy with the key that the rows are sorted by.

It also has the sortDesc boolean property which is true if we sort in descending order.

Light Weight Tables

b-table-lite is a light version of the b-table component.

It’s great for creating a simple table.

It doesn’t have most of the features of b-table like filtering, sorting, pagination, and other dynamic features.

Conclusion

We can add filtering to our table with the filter prop.

Also, we can force refresh a table and add provider functions to load data instead of assigning the data directly to it.

Categories
BootstrapVue

BootstrapVue — Customizing Sidebars and Spinners

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 sidebars and adding spinners.

Width

We can add a width prop to adjust the sidebar’s width.

It’s set to 320px by default.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" title="Sidebar" width="250px">
      <div class="px-3 py-2">
        <p>foo</p>
        <b-img src="http://placekitten.com/200/200" fluid thumbnail></b-img>
      </div>
    </b-sidebar>
  </div>
</template>

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

We set the sidebar to 250px wide by passing that into the width prop.

Disable Slide Transition

We can use the no-slide prop to disable slide transition:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" title="Sidebar" no-slide>
      <div class="px-3 py-2">
        <p>foo</p>
        <b-img src="http://placekitten.com/200/200" fluid thumbnail></b-img>
      </div>
    </b-sidebar>
  </div>
</template>

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

Now we won’t see any transitions.

Z-Index

The z-index can be changed with the z-index prop.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" title="Sidebar" z-index='100'>
      <div class="px-3 py-2">
        <p>foo</p>
        <b-img src="http://placekitten.com/200/200" fluid thumbnail></b-img>
      </div>
    </b-sidebar>
  </div>
</template>

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

Hide the Default Header

We can populate the default slot to customize the content.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" no-header>
      <template v-slot:default="{ hide }">
        <div class="px-3 py-2">
          <b-button variant="primary" block @click="hide">Close Sidebar</b-button>
          <p>foo</p>
          <b-img src="http://placekitten.com/200/200" fluid thumbnail></b-img>
        </div>
      </template>
    </b-sidebar>
  </div>
</template>

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

We disabled the header with the no-header prop.

Then we pass the hide function from the slot’s scope into @click directive as the click handler.

The hide function will close the sidebar when it’s called.

Footer

We can customize the footer with the footer slot.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" no-header>
      <div class="px-3 py-2">
        <p>foo</p>
        <b-img src="http://placekitten.com/200/200" fluid thumbnail></b-img>
      </div>
      <template v-slot:footer="{ hide }">
        <div class="px-3 py-2">
          <b-button variant="primary" block @click="hide">Close Sidebar</b-button>
        </div>
      </template>
    </b-sidebar>
  </div>
</template>

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

We have the v-slot:footer directive on the template tag to let us populate the footer.

It also has the hide function to hide the sidebar.

So we can add a button that calls hide when it’s clicked.

Lazy Rendering

We can add the lazy prop to only render the content inside when the sidebar is being shown.

Backdrop

We can enable the backdrop with the backdrop prop.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" backdrop>
      <div class="px-3 py-2">
        <p>foo</p>
        <b-img src="http://placekitten.com/200/200" fluid thumbnail></b-img>
      </div>
    </b-sidebar>
  </div>
</template>

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

Now we see a dark backdrop when the sidebar is opened.

Spinners

We can add a spinner to our Vue app with the b-spinner component.

For example, we can write:

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

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

to add a simple spinner.

Spinner Types

We can change the type of the spinner.

The default type is called border which is a spinning circle.

Or we can display a throbbing style indicator.

To change our spinner into the throbbing kind, we can set the type to grow .

We can write:

<template>
  <div id="app">
    <b-spinner type="grow"></b-spinner>
  </div>
</template>

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

Spinner Color Variants

The variant prop can be used to change the spinner color.

For example, we can write:

<template>
  <div id="app">
    <b-spinner variant="success"></b-spinner>
  </div>
</template>

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

to make it green.

Size

The size can be changed with the small prop to make it small:

<template>
  <div id="app">
    <b-spinner small></b-spinner>
  </div>
</template>

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

Other than that, we can also use custom CSS to style the spinner our way:

<template>
  <div id="app">
    <b-spinner style="width: 6rem; height: 6rem;"></b-spinner>
  </div>
</template>

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

We made it bigger than the default with the styles.

Conclusion

Sidebar transitions can be disabled.

Also, any sidebar content can be customized.

A spinner lets us display an animate icon to indicate progress.