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.

Categories
BootstrapVue

BootstrapVue — Open and Close 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 open and close modal components.

The v-b-modal Directive

We can use the v-b-modal to open a modal.

It can take a modifier or an ID string for the modal ID.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-modal.modal>open</b-button>
    <b-modal id="modal" title="Hello">
      <p>Hello!</p>
    </b-modal>
  </div>
</template>

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

We can also write:

<template>
  <div id="app">
    <b-button v-b-modal="'modal'">open</b-button>
    <b-modal id="modal" title="Hello">
      <p>Hello!</p>
    </b-modal>
  </div>
</template>

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

We’ve to pass in the string in quotes as the value of v-b-modal .

The button in both examples opens the modal.

Open and Close Modals Programmatically

We can use the this.$bvModal.show() and this.$bvModal.hide() to open and close the modal respectively.

They will be available when we register the BootstrapVue plugin or the ModalPlugin .

For instance, we can write:

<template>
  <div id="app">
    <b-button @click="$bvModal.show('modal')">Open</b-button>

    <b-modal id="modal" hide-footer>
      <template v-slot:modal-title>Hello</template>
      <div>
        <h3>Hello!</h3>
      </div>
      <b-button block @click="$bvModal.hide('modal')">Close</b-button>
    </b-modal>
  </div>
</template>

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

We have the b-modal component, which is opened with the $bvModal.show method.

We pass in the ID of the modal to open it.

Likewise, we called $bvModal.hide to hide the modal.

We also pass in the ID there.

The show, hide, and toggle Methods

BootstrapVue models can also be opened with the show method.

It can be hidden with the hide method.

And it can be toggled on and off with the toggle method.

For example, we can write:

<template>
  <div id="app">
    <b-button id="show-btn" @click="showModal">Open</b-button>
    <b-button id="toggle-btn" @click="toggleModal">Toggle</b-button>

    <b-modal ref="modal" hide-footer title="Hello">
      <div>
        <h3>Hello</h3>
      </div>
      <b-button block @click="hideModal">Close</b-button>
      <b-button block @click="toggleModal">Toggle</b-button>
    </b-modal>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    showModal() {
      this.$refs["modal"].show();
    },
    hideModal() {
      this.$refs["modal"].hide();
    },
    toggleModal() {
      this.$refs["modal"].toggle("#toggle-btn");
    }
  }
};
</script>

We have methods that are called the ref of the modal to open and close it.

The ref prop of the b-modal sets the ref name.

Then in the methods, we can use this.$refs to get the modal by its ref name.

Once we accessed the ref, we can call the show , hide , and toggle methods on the ref.

For the toggle method, we have to pass in the selector for the button that lets us toggle the modal.

v-model

b-modal components can bind to a model with the v-model directive.

It’ll bind the visible state of the modal to the state variable.

For example, we can write:

<template>
  <div id="app">
    <b-button @click="modalShow = !modalShow">Open</b-button>

    <b-modal v-model="modalShow">{{modalShow}}</b-modal>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      modalShow: false
    };
  }
};
</script>

We have the modalShow state, which we bind to the modal state with v-modal .

modalShow will be true if it’s open and false otherwise.

So when we open the modal, the content will be ‘true’.

Scoped Slot Methods

We can emit the bv::show::modal , bv::hide::modal , and bv::toggle::modal on the $root to control the opening and closing of modals.

For example, we can write:

<template>
  <div id="app">
    <b-button @click="showModal" ref="btnShow">Open</b-button>
    <b-button @click="toggleModal" ref="btnToggle">Toggle</b-button>

    <b-modal id="modal">
      <div class="d-block">Hello</div>
      <b-button @click="hideModal">Close</b-button>
      <b-button @click="toggleModal">Toggle</b-button>
    </b-modal>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    showModal() {
      this.$root.$emit("bv::show::modal", "modal", "#btnShow");
    },
    hideModal() {
      this.$root.$emit("bv::hide::modal", "modal", "#btnShow");
    },
    toggleModal() {
      this.$root.$emit("bv::toggle::modal", "modal", "#btnToggle");
    }
  }
};
</script>

We have 2 buttons outside the modal to open and toggle the modal.

We set the ref on each button so that we can use them as the 3rd argument of the $emit method.

This way, we can control the modal’s open status.

The 2nd argument is the ref of the modal.

Once the events are emitted, then we can show, hide, or toggle the modal.

The bv::show::modal event shows the modal when it’s emitted.

The bv::hide::modal event hides the modal when it’s emitted.

And the bv::toggle::modal event toggles the modal when it’s emitted.

Conclusion

We can control how models and opened and close and in various ways, including emitting events, and calling built-in methods.