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.

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.