Categories
BootstrapVue

BootstrapVue — Customizing 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 tooltips.

Positioning

We can change the positing with modifiers for the v-b-tooltip to change the placement.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-tooltip.hover.bottomright title="Tooltip title">hover</b-button>
  </div>
</template>

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

<style>
#app {
  height: 100vh;
  width: 100vw;
  margin: 50vw 50vh;
}
</style>

We have the bottomright prop so that the tooltip is placed to the bottom right of the button.

Focus Trigger

The focus trigger renders the a tag rather than the button tag.

So tabindex='0' must be included.

Therefore, we’ve to write:

<template>
  <div id="app">
    <b-button href="#" tabindex="0" v-b-tooltip.focus title="Tooltip">Link button</b-button>
  </div>
</template>

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

Disabled Elements

We can trigger a tooltip from a disable button by trigger it from its wrapper element instead.

For example, we can write:

<template>
  <div id="app">
    <span id="disabled" tabindex="0">
      <b-button disabled>Disabled button</b-button>
    </span>
    <b-tooltip target="disabled">Disabled</b-tooltip>
  </div>
</template>

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

We put the id on the span instead of the b-button , so we can trigger the tooltip when we hover over the button.

b-tooltip Component Usage

We can style the content inside a tooltip if we use the b-tooltip component.

For example, we can write:

<template>
  <div id="app">
    <b-button id="tooltip">button</b-button>
    <b-tooltip target="tooltip">Hello
      <b>World</b>
    </b-tooltip>
  </div>
</template>

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

We made the word ‘World’ bold with the b tag.

Variants and Custom Class

b-tooltip takes the variant prop to let us change the variant.

For example, we can write:

<template>
  <div id="app">
    <b-button id="tooltip">button</b-button>
    <b-tooltip target="tooltip" variant="info">hello</b-tooltip>
  </div>
</template>

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

We set the variant to 'info' , so the tooltip is green.

Also, we can add the custom-class prop to set a custom class.

For instance, we can write:

<template>
  <div id="app">
    <b-button id="tooltip">button</b-button>
    <b-tooltip target="tooltip" custom-class="tooltip">hello</b-tooltip>
  </div>
</template>

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

<style>
.tooltip {
  font-weight: bold;
}
</style>

Then the text in the tooltip is bold since we set the custom-class to 'tooltip' .

Show and Hide Tooltips Programmatically

We can set the show prop to show and hide a tooltip programmatically.

For example, we can write:

<template>
  <div id="app">
    <b-button @click="show = !show">button</b-button>
    <b-button id="tooltip">button with tooltip</b-button>
    <b-tooltip :show='show' target="tooltip" custom-class="tooltip">hello</b-tooltip>
  </div>
</template>

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

We have a button that toggles the show value.

The show prop is added to the b-tooltip so we can see the tooltip when show is true .

We can also submit the 'open' and 'close' events to open and close the tooltip.

For example, we can write:

<template>
  <div id="app">
    <b-button @click="open">open</b-button>
    <b-button @click="close">close</b-button>
    <b-button id="tooltip">tooltip button</b-button>
    <b-tooltip target="tooltip" ref="tooltip">hello</b-tooltip>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    open() {
      this.$refs.tooltip.$emit("open");
    },
    close() {
      this.$refs.tooltip.$emit("close");
    }
  }
};
</script>

We assigned a ref to the b-tooltip component.

Also, we added the open and close method to emit the open and close events respectively.

That will open or close the tooltip.

Then when we click the open button, the tooltip will open beside the ‘tooltip button’ button.

When we click close, we close the tooltip.

Disable a Tooltip Programmatically

We can disable a tooltip with a prop or a ref event.

For example, we can write:

<template>
  <div id="app">
    <b-button id="tooltip">tooltip button</b-button>
    <b-tooltip target="tooltip" disabled>hello</b-tooltip>
  </div>
</template>

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

to disable the tooltip with the disable prop.

We can also disable a tooltip with the ref.

For example, we can write:

<template>
  <div id="app">
    <b-button [@click](http://twitter.com/click "Twitter profile for @click")="toggleDisable">toggle disable</b-button>
    <b-button id="tooltip">tooltip button</b-button>
    <b-tooltip ref="tooltip" target="tooltip">hello</b-tooltip>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      disabled: false
    };
  },
  methods: {
    toggleDisable() {
      this.disabled = !this.disabled;
      if (this.disabled) {
        this.$refs.tooltip.$emit("disable");
      } else {
        this.$refs.tooltip.$emit("enable");
      }
    }
  }
};
</script>

We can disable or enable the tooltip with the this.$refs.tooltip.$emit(“disable”); and this.$refs.tooltip.$emit(“enable”); calls respectively.

Therefore, the ‘toggle disable’ button will toggle the disabled status of the tooltip.

Conclusion

We can enable or disable a tooltip programmatically.

To do that, we can emit events or set props.

The positioning of the tooltip can also be changed.

Categories
BootstrapVue

BootstrapVue — Table Transitions and Sorting

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 transitions and sorting.

Table Body Transition

We can add table body transitions to our table’s body.

To do that, we can add the tbody-transition-prois to add transition-group properties in an object.

The tbody-transition-handlers kets us add transition-groip event handlers from an object.

primary-lkey is a string that specifies the fields to use as a unique row key.

For instance, we can write:

<template>
  <div id="app">
    <b-table primary-key="id" :tbody-transition-props="transProps" :items="items" :fields="fields"></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      fields: [
        { key: "id", sortable: true },
        { key: "firstName", sortable: true },
        { key: "lastName", sortable: true }
      ],
      transProps: {
        name: "flip-list"
      },
      items: [
        { id: 1, firstName: "alex", lastName: "green" },
        {
          id: 2,
          firstName: "may",
          lastName: "smith"
        },
        { id: 3, firstName: "james", lastName: "jones" }
      ]
    };
  }
};
</script>

<style>
table .flip-list-move {
  transition: transform 1s;
}
</style>

We added transition effects when we sort the table rows.

To do that, we added the tbody-transition-props prop which is set to the transProps object.

The object has a name for the transition.

The name should match the prefix class of the CSS transition.

Therefore, in the style tag, we have the flip-list-move class, which starts with flip-list .

primary-key is also set to the unique key column in our table, which is id .

We make the sortable with the sortable property in each fields array entry.

Now when we click the sort button on each field, we’ll see a fade effect displayed.

Sorting

BootstrapVue tables are sortable.

We can specify the props for sorting the tables.

To specify the columns to be sorted, we can use the sort-by prop.

The direction can be set by sort-desc set to true or false .

This way, we can sort the value from highest to lowest or vice versa respectively.

When foot-clone is set, the footer headings will also allow sorting by clicking.

This is true even if we have custom footers.

For example, we can write:

<template>
  <div id="app">
    <b-table sort-by="id" sortDesc :items="items" :fields="fields"></b-table>
  </div>
</template>

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

We added the sort-by prop with the name of the field we want to sort.

It’s set to id to sort by id .

sortDesc lets us sort the column in descending order.

Therefore we have the rows sorted by the id column in descending order.

Customizing Sort Icons

We can customize the CSS to change the sort icon.

Sort Compare

We can change how the entries are compared with the sort-compare prop set to a function to let us customize sorting.

For instance, we can write:

<template>
  <div id="app">
    <b-table sort-compare='sortCompare' :items="items" :fields="fields"></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      fields: [
        { key: "id", sortable: true },
        { key: "firstName", sortable: true },
        { key: "lastName", sortable: true }
      ],
      items: [
        { id: 1, firstName: "alex", lastName: "green" },
        {
          id: 2,
          firstName: "may",
          lastName: "smith"
        },
        { id: 3, firstName: "james", lastName: "jones" }
      ]
    };
  },
  methods: {
    sortCompare(
      aRow,
      bRow,
      key,
      sortDesc,
      formatter,
      compareOptions,
      compareLocale
    ) {
      return aRow[key].localeCompare(bRow[key], compareLocale, compareOptions);
    }
  }
};
</script>

We gave the sortCompare which we set as the value of sort-compare .

In the method, we can pass in compareLocale and compareOptions to the localeCompare method of a string to sort them.

Conclusion

We can add table body transitions to add effects when manipulating rows.

Also, we can sort columns our way with the built-in props or a custom sorting function.

Categories
BootstrapVue

BootstrapVue — Customizing Progress Bars and Sidebars

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 progress bars and add sidebars.

Width and Height

We can change the width of the b-progress component the way we like.

For instance, we can write:

<template>
  <div id="app">
    <b-progress :value="value" class="w-50 mb-2"></b-progress>
  </div>
</template>

<script>
export default {
  data() {
    return {
      value: 75
    };
  }
};
</script>

to make it fill half the screen.

The height can also be changed.

For example, we can write:

<template>
  <div id="app">
    <b-progress :value="value" height="2rem"></b-progress>
  </div>
</template>

<script>
export default {
  data() {
    return {
      value: 75
    };
  }
};
</script>

We set the height to 2rem , so the progress bar would be taller.

Backgrounds

We can change the background of the progress bar the way we like.

This can be done with the variant prop.

For example, we can write:

<template>
  <div id="app">
    <b-progress :value="value" variant="success"></b-progress>
  </div>
</template>

<script>
export default {
  data() {
    return {
      value: 75
    };
  }
};
</script>

Then we see a green bar because we set the variant to 'success' .

Striped Backgrounds

The background of a progress bar can be made striped.

To make it striped, we add the striped prop.

For example, we can write:

<template>
  <div id="app">
    <b-progress :value="value" striped></b-progress>
  </div>
</template>

<script>
export default {
  data() {
    return {
      value: 75
    };
  }
};
</script>

Now the bar is striped.

Animated Backgrounds

The background of the progress bar can be also be animated.

We just have to set the animated prop to do that:

<template>
  <div id="app">
    <b-progress :value="value" animated></b-progress>
  </div>
</template>

<script>
export default {
  data() {
    return {
      value: 75
    };
  }
};
</script>

Sidebar

We can create a sidebar with BootstrapVue.

This is a component that’s available since 2.10.0.

To create one, we use the b-sidebar component:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" title="Sidebar" shadow>
      <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 have the v-b-toggle directive.

The sidebar modifier matches the name of the id of the b-sidebar to let us open the sidebar.

On the b-siderbar component, we set the title prop, which sets the title.

shadow enables shadows.

And the rest of the content displayed below the title.

Placement

The placement can be changed with props.

The right prop will put the sidebar on the right instead of the left.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" title="Sidebar" right  shadow>
      <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 the sidebar opens from the right instead of the left.

Styling Variants

We can use the bg-variant to change the styling variant of the background.

The text-variant is used to change the styling of the text.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" title="Sidebar" bg-variant="success" text-variant="light" shadow>
      <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>

Then the text is white since text-variant is light .

bg-variant is success so the background is green.

Borders

We can add borders with BootstrapVue’s border utility classes.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-toggle.sidebar>Toggle</b-button>
    <b-sidebar id="sidebar" title="Sidebar" sidebar-class="border-right border-success">
      <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 added the sidebar-class prop to let us set the border class.

border-right adds the border to the right.

border-success makes the border green.

Conclusion

The progress bar can be styled the way we want.

Also, we can add sidebars with BootstrapVue.

We can add content and control background, border, and text colors.

Categories
BootstrapVue

BootstrapVue — Table Rows and Columns

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 sticky columns and row selection.

Sticky Columns

We can make columns sticky with the stickyColumn property in a field entry.

For instance, we can write:

<template>
  <div id="app">
    <b-table :items="items" sticky-header :fields="fields"></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      fields: [
        {
          key: "id",
          stickyColumn: true,
          isRowHeader: true,
          variant: "primary"
        },
        "a",
        "b",
        { key: "c", stickyColumn: true, variant: "info" },
        "d",
        "e",
        "f",
        "g",
        "h",
        "i"
      ],
      items: [
        {
          id: 1,
          a: 0,
          b: 1,
          c: 2,
          d: 3,
          e: 4,
          f: 5,
          g: 6,
          h: 7,
          i: 8
        },
        {
          id: 2,
          a: 0,
          b: 1,
          c: 2,
          d: 3,
          e: 4,
          f: 5,
          g: 6,
          h: 7,
          i: 8
        },
        {
          id: 3,
          a: 0,
          b: 1,
          c: 2,
          d: 3,
          e: 4,
          f: 5,
          g: 6,
          h: 7,
          i: 8
        }
      ]
    };
  }
};
</script>

We have the stickyColumn property set to true in our field entries.

We also have the sticky-header to keep the header displaying.

Now the Id and C columns will always be shown.

Row Details

We can add row details into our table rows.

To do that, we can populate the row-details slot.

For example, we can write:

<template>
  <div id="app">
    <b-table :items="items" :fields="fields">
      <template v-slot:cell(showDetails)="row">
        <b-button
          size="sm"
          @click="row.toggleDetails"
          class="mr-2"
        >{{ row.detailsShowing ? 'Hide' : 'Show'}} Details</b-button>
      </template>

<template v-slot:row-details="row">
        <b-card>
          <b-row class="mb-2">
            <b-col>
              <b>Age:</b>
            </b-col>
            <b-col>{{ row.item.age }}</b-col>
          </b-row>

<b-button size="sm" @click="row.toggleDetails">Hide Details</b-button>
        </b-card>
      </template>
    </b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      fields: ["firstName", "lastName", "showDetails"],
      items: [
        { firstName: "alex", lastName: "green", age: 20 },
        {
          firstName: "may",
          lastName: "smith",
          age: 20
        },
        { firstName: "james", lastName: "jones", age: 22 }
      ]
    };
  }
};
</script>

We referenced the row.toggleDetails method in the cell(showDetails) slot.

This lets us toggle the details.

row.detailsShowing is true if the row details are showing and false otherwise.

Then we populated the row-details slots.

It also has access to the row data.

row.item has the data.

So we can access the age with row.item.age .

It also has access to the toggleDetails method to toggle off the details.

Row Selection

We can let users select rows on the table.

To do that, we can add the select-mode prop.

The value can be 'multi' for mukltuple selection.

'single' for single selection.

And 'range' for letting people shift-click a range of rows. Ctrl-click will let them toggle the selected row.

Rows can be programmatically selected or unselected.

selectRow(index) lets us select a row with the given index.

unselectRow(index) unselectes a row with the given index.

selectAllRows() selects all rows.

clearSelected() unselects all rows.

isRowSelected(index) returns true if a row is selected.

We can write:

<template>
  <div id="app">
    <b-table :items="items" selectable select-mode="multi"></b-table>
  </div>
</template>

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

to make the rows selectable.

We added selectable to make the rows selectable and select-mode is set to 'multi' to let users select any rows they like.

Then to call the methods we listed above, we can write:

<template>
  <div id="app">
    <b-button [@click](http://twitter.com/click "Twitter profile for @click")='clearSelected'>clear selection</b-button>
    <b-table ref='selectableTable' :items="items" selectable select-mode="multi"></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      items: [
        { firstName: "alex", lastName: "green" },
        {
          firstName: "may",
          lastName: "smith"
        },
        { firstName: "james", lastName: "jones" }
      ]
    };
  },
  methods: {
    clearSelected() {
      this.$refs.selectableTable.clearSelected();
    }
  }
};
</script>

We assigned a ref to the b-table . Then we call the clearSelected method on it to clear the selected rows.

Conclusion

We can add make columns sticky.

Also, we can add row details to our table rows that we can toggle.

Finally, we can let users select the rows and clear them.

Categories
BootstrapVue

BootstrapVue — Popovers and Progress Bars

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 popovers and add progress bars.

Hiding and Showing Popovers

We can open and hide popovers the way that we want to show them with the this.$root.emit method.

The method lets us emit events globally and so it can be used to open more than one popover.

For example, we can write:

<template>
  <div id="app" class="text-center">
    <b-button v-b-popover.hover.top="'Popover 1'" title="Title 1">Button 1</b-button>
    <b-button v-b-popover.hover.top="'Popover 2'" title="Title 2">Button 2</b-button>
    <b-button @click='showAll'>Show All</b-button>
  </div>
</template>

<script>
export default {
  methods: {
    showAll() {
      this.$root.$emit("bv::show::popover");
    }
  }
};
</script>

<style>
#app {
  margin: 200px;
}
</style>

We have 2 buttons with popovers.

And we have the Show All button.

We have the showAll method to emit the 'bv::show::popover' event to show all popovers.

Also, we can write:

<template>
  <div id="app" class="text-center">
    <b-button id="popover-1" v-b-popover.hover.top="'Popover 1'" title="Title 1">Button 1</b-button>
    <b-button v-b-popover.hover.top="'Popover 2'" title="Title 2">Button 2</b-button>
    <b-button @click="showOne">Show 1</b-button>
  </div>
</template>

<script>
export default {
  methods: {
    showOne() {
      this.$root.$emit("bv::show::popover", "popover-1");
    }
  }
};
</script>

<style>
#app {
  margin: 200px;
}
</style>

We have the showOne method with 'popover-1' as the second argument.

This is the ID of the popover we want to open.

Now when we click the Show 1 button, we see the first popover open.

Likewise, there is the bv::hide::popover to hide the popover.

There’s the bv::disable::popover to disable them so they can’t be opened.

And there is bv::enable::popover to enable them so they can be opened.

We can listen to these events with this.$root.$on .

For example, we can write:

export default {
  mounted() {
    this.$root.$on('bv::popover::show', bvEventObj => {
      console.log('bvEventObj:', bvEventObj)
    })
  }
}

The callback will be run when those events are triggered.

Progress

BootstrapVue provides us with the progress component to let us display the progress of something.

To add one, we can use the b-progress and the b-progress-bar components.

For example, we can write:

<template>
  <div id="app">
    <b-progress class="mt-2" :max="max" show-value>
      <b-progress-bar :value="value * (6 / 10)" variant="success"></b-progress-bar>
      <b-progress-bar :value="value * (2.5 / 10)" variant="warning"></b-progress-bar>
      <b-progress-bar :value="value * (1.5 / 10)" variant="danger"></b-progress-bar>
    </b-progress>

<b-button class="mt-3" @click="randomValue">random number</b-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      max: 100,
      value: 0
    };
  },
  methods: {
    randomValue() {
      this.value = Math.random() * this.max;
    }
  }
};
</script>

We have the b-progress component which houses the b-progress-bar component.

We can have bar with multiple values.

In the example above, we have 6 / 10 of it being green with because of the variant is set to 'success' .

Then a quarter of the bar is yellow since we the variant to warning in the 2nd b-progress-bar .

Then we have 15% of it being red since variant is set to danger in the 3rd bar.

The value determines the portion of the bar that’s filled.

max is the maximum value.

show-value indicates whether we want to show the value or not.

Labels

We can use the show-progress to show the percentage of the max value.

Or we can use the show-value props to show the current absolute value.

For example, we can write:

<template>
  <div id="app">
    <b-progress show-value :value="value" :max="max"></b-progress>
  </div>
</template>

<script>
export default {
  data() {
    return {
      max: 100,
      value: 75
    };
  }
};
</script>

Then we see the absolute value in the progress bar.

Custom Progress Label

We can customize the progress label the way we like.

For example, we can write:

<template>
  <div id="app">
    <b-progress :value="value" :max="max" height="2rem">
      <b-progress-bar :value="value">
        <strong>{{ value.toFixed(2) }} / {{ max }}</strong>
      </b-progress-bar>
    </b-progress>
  </div>
</template>

<script>
export default {
  data() {
    return {
      max: 100,
      value: 75
    };
  }
};
</script>

We have b-progress-bar which takes the value and round it to 2 decimal places.

We also take the max value and display it after it.

Conclusion

Popovers can be shown, hidden, enabled, or disabled by emitting events.

Also, we can create progress bars with the b-progress-bar components.