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.

Categories
BootstrapVue

BootstrapVue —Customizing Overlays and 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 customize overlays to our app.

We also look at how to add pagination buttons to our page.

Width

We can change the b-overlay to an inline-block component, then we can change the width.

For example, we can write:

<b-overlay class="d-inline-block">
  ...
</b-overlay>

Now we can change the width.

Non-Wrapping Mode

We can add the no-wrap prop to disable rendering of the wrapping and ignore the default slot.

For example, we can write:

<template>
  <div id="app">
    <div>baz</div>
    <b-overlay no-wrap show>
      <b-card title="Card">
        <b-card-text>foo</b-card-text>
      </b-card>
    </b-overlay>
    <div>qux</div>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

This way, everything is behind the overlay instead of only what’s inside the b-overlay component.

Pagination

We can add pagination buttons into our app with the b-pagination component.

For example, we can write:

<template>
  <div id="app">
    <b-pagination 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>

We have the b-pagination component that takes a few props.

v-model binds the current page number to the page state.

total-rows has the total number of rows of our data.

per-page is how many rows we want to display per page.

Now we get a series of pagination links that we can click.

The page value in the p element will also be updated.

Button Content

The button content can be customized.

For example, we can write:

<template>
  <div id="app">
    <b-pagination
      v-model="page"
      :total-rows="rows"
      :per-page="perPage"
      first-text="First"
      prev-text="Prev"
      next-text="Next"
      last-text="Last"
    ></b-pagination>

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

We have the first-text prop to set the content of the button to go to the first page.

The prev-text prop is used to set the content of the button to go to the previous page.

The next-text prop is used to set the content of the button to fo to the next page.

And the last-text prop is used to set the content of the button to go to the last page.

If we want to set HTML content for the buttons, we can populate the slots for them.

For example, we can write:

<template>
  <div id="app">
    <b-pagination v-model="page" :total-rows="rows" :per-page="perPage">
      <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>

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

We populated the first-text slot to set the content for the button to go to the first page.

We populated the next-text slot to set the content for the button to go to the next page.

Also, we populated the prev-text slot to set the content for the button to go to the previous page.

We populated the last-text slot to set the content for the button to go to the last page.

The ellipsist-text is populated with the content for the ellipsis.

We replaced the default text with flashing dots.

The page slot is used for populating content for the page number.

We can get the active and page states from it.

active indicates if the page is active.

page is the page number.

Conclusion

We can change the width of the overlay as long we make it an inline-block component.

The pagination lets us create a pagination bar to navigate through pages.

We can populate the pagination items with our own content.

Categories
BootstrapVue

BootstrapVue — Overlays

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 overlays to our app.

Overlay

We can use the b-overlay component to visually obscure a particular element or component and its content.

It’s available since BootstrapVue 2.7.0.

For example, we can create one by writing:

<template>  
  <div id="app">  
    <b-overlay :show="show">  
      <b-card title="Card">  
        <b-card-text>foo</b-card-text>  
      </b-card>  
    </b-overlay>  
    <b-button @click="show = !show">Toggle overlay</b-button>  
  </div>  
</template>  
<script>  
export default {  
  name: "App",  
  data() {  
    return {  
      show: false  
    };  
  }  
};  
</script>

We have a b-card inside the b-overlay component.

b-overlay takes a show prop to let us set when to show the overlay.

When we click Toggle overlay, then we’ll toggle the overlay on and off as we toggle the show state between true and false .

When the overlay is shown, then we’ll see the card content covered in gray and a spinner in the middle.

Overlay Backdrop Color

We can change the backdrop color of an overlay.

For example, we change the opacity with the opacity prop:

<template>  
  <div id="app">  
    <b-overlay :show="show" opacity="0.5">  
      <b-card title="Card">  
        <b-card-text>foo</b-card-text>  
      </b-card>  
    </b-overlay>  
    <b-button @click="show = !show">Toggle overlay</b-button>  
  </div>  
</template>  
<script>  
export default {  
  name: "App",  
  data() {  
    return {  
      show: false  
    };  
  }  
};  
</script>

We set opacity to 0.5, so we’ll see a translucent overlay.

Also, we can change how the background is blurred with the blur prop:

<template>  
  <div id="app">  
    <b-overlay :show="show" blur="2px">  
      <b-card title="Card">  
        <b-card-text>foo</b-card-text>  
      </b-card>  
    </b-overlay>  
    <b-button @click="show = !show">Toggle overlay</b-button>  
  </div>  
</template>  
<script>  
export default {  
  name: "App",  
  data() {  
    return {  
      show: false  
    };  
  }  
};  
</script>

The value is specified in pixels.

Spinner Styling

We can change the spinner styling with various props.

The spinner-type prop lets us change the spinner type.

spinner-variant lets us change the color for the spinner.

spinner-small makes the spinner smaller if it’s set to true .

We can write:

<template>  
  <div id="app">  
    <b-overlay show spinner-variant="primary" spinner-type="grow" spinner-small>  
      <b-card title="Card">  
        <b-card-text>foo</b-card-text>  
      </b-card>  
    </b-overlay>  
  </div>  
</template>  
<script>  
export default {  
  name: "App"  
};  
</script>

Now get a different spinner than the default.

We have a flashing dot.

primary makes the spinner blue.

spinner-small made it small.

Corner Rounding

We can round the corners of the overlay.

To do that, we can set the rounded prop.

The possible values are:

  • true — default styling
  • false — no rounding
  • 'sm' — small rounded corners
  • 'lg' — large rounded corners
  • 'pill' — pill style rounded corners
  • 'circle' — circular or oval rounding
  • 'top' — rounding only the top 2 corners
  • 'bottom' — touring only the bottom 2 corners
  • 'left' — rounding only the 2 left corners
  • 'right' — rounding only the 2 right corners

For example, we can write:

<template>  
  <div id="app">  
    <b-overlay rounded="circle" show>  
      <b-card title="Card">  
        <b-card-text>foo</b-card-text>  
      </b-card>  
    </b-overlay>  
  </div>  
</template>  
<script>  
export default {  
  name: "App"  
};  
</script>

Since we set rounded to 'circle' , we’ll see an oval overlay.

Custom Overlay Content

We can customize the overlay’s content.

To do that, we populate the overlay slot.

For example, we write:

<template>  
  <div id="app">  
    <b-overlay show>  
      <b-card title="Card">  
        <b-card-text>foo</b-card-text>  
      </b-card>  
      <template v-slot:overlay>  
        <div>loading</div>  
      </template>  
    </b-overlay>  
  </div>  
</template>  
<script>  
export default {  
  name: "App"  
};  
</script>

Then we see ‘loading’ on our overlay instead of a spinner.

Centering Overlay Content

The content of an overlay is centered by default.

To disable that, we can set the no-center prop to true :

<template>  
  <div id="app">  
    <b-overlay no-center show>  
      <b-card title="Card">  
        <b-card-text>foo</b-card-text>  
      </b-card>  
    </b-overlay>  
  </div>  
</template>  
<script>  
export default {  
  name: "App"  
};  
</script>

Now the spinner will be shown on the top left corner.

Conclusion

We can add overlays to obscure the content behind it.

The overlay can be customized to do what we want.