Categories
JavaScript Vue

Useful Vue Data Grid Components

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at some data grid components that we can use to build data grids.

vue-handsontable-official

This is a Vue data grid that looks and feels like a spreadsheet. It’s the official Vue wrapper for Handsontable.

We can run:

npm install handsontable @handsontable/vue

to install it. Then we can use it as follows:

<template>
  <div id="app">
    <hot-table
      licenseKey="non-commercial-and-evaluation"
      :data="data"
      :colHeaders="true"
      :rowHeaders="true"
      width="600"
      height="300"
    ></hot-table>
  </div>
</template>
<script>
import { HotTable } from "@handsontable/vue";
export default {
  data() {
    return {
      data: [
        ["", "Mazda", "Honda", "Toyota", "Volvo"],
        ["2019", 10, 11, 12, 13],
        ["2020", 20, 11, 14, 13],
        ["2021", 30, 15, 12, 13]
      ]
    };
  },
  components: {
    HotTable
  }
};
</script>
<style lang="scss">
@import "~handsontable/dist/handsontable.full.css";
</style>

In the code above, we registered the HotTable component in our component. Then we have the data model, which we pass int the data prop of the hot-table component.

Also, we set colHeaders and rowHeaders to true so that we see the column and row headings. This should result in a data grid that looks like a spreadsheet, with letters as column headers and numbers as row headers.

Like a spreadsheet, we can also add context menus for the cells by adding the contextMenu object as follows:

<template>
  <div id="app">
    <hot-table
      licenseKey="non-commercial-and-evaluation"
      :data="data"
      :colHeaders="true"
      :rowHeaders="true"
      width="600"
      height="300"
      :contextMenu="contextMenu"
    ></hot-table>
  </div>
</template>
<script>
import { HotTable } from "@handsontable/vue";
import Handsontable from "handsontable";
export default {
  data() {
    return {
      data: [
        ["", "Tesla", "Mercedes", "Toyota", "Volvo"],
        ["2019", 10, 11, 12, 13],
        ["2020", 20, 11, 14, 13],
        ["2021", 30, 15, 12, 13]
      ],
      contextMenu: {
        items: {
          row_above: {
            name: "Insert row above this one"
          },
          row_below: {},
          separator: Handsontable.plugins.ContextMenu.SEPARATOR,
          clear_custom: {
            name: "Clear all cells",
            callback() {
              this.clear();
            }
          }
        }
      }
    };
  },
  components: {
    HotTable
  }
};
</script>
<style lang="scss">
@import "~handsontable/dist/handsontable.full.css";
</style>

We added the contextMenu object, which has the row_above property for adding a context menu entry for inserting a new row above the current one. Then we added the row_below property to add an Insert row below menu item, but set the value to an empty object so that we keep the default settings.

Then we added a clear_custom property to add an entry to clear all cells.

There’re many more options, including customizing the editor, changing how cells are rendered, integration with Vuex and more.

The full list of options are at https://handsontable.com/docs/7.4.0/tutorial-introduction.html.

It’s free for non-commercial and evaluation purpose, but it’s a paid library for commercial purposes.

vue-sorted-table

vue-sorted-table is another table component that automatically generates a table from data. It makes adding the column sorting feature easy. To install it, we run:

npm install --save vue-sorted-table

Then to use it, we write the following code:

main.js :

import Vue from "vue";
import App from "./App.vue";
import SortedTablePlugin from "vue-sorted-table";
Vue.use(SortedTablePlugin);
Vue.config.productionTip = false;
new Vue({
  render: h => h(App)
}).$mount("#app");

App.vue :

<template>
  <div id="app">
    <sorted-table :values="values">
      <thead>
        <tr>
          <th scope="col" style="text-align: left; width: 10rem;">
            <sort-link name="id">ID</sort-link>
          </th>
          <th scope="col" style="text-align: left; width: 10rem;">
            <sort-link name="name">Name</sort-link>
          </th>
          <th scope="col" style="text-align: left; width: 10rem;">
            <sort-link name="hits">Age</sort-link>
          </th>
        </tr>
      </thead>
      <tbody slot="body" slot-scope="sort">
        <tr v-for="value in sort.values" :key="value.id">
          <td>{{ value.id }}</td>
          <td>{{ value.name }}</td>
          <td>{{ value.age }}</td>
        </tr>
      </tbody>
    </sorted-table>
  </div>
</template>
<script>
export default {
  name: "App",
  data: function() {
    return {
      values: [
        { name: "James", id: 2, age: 33 },
        { name: "Mary", id: 1, age: 42 },
        { name: "Alex", id: 3, age: 79 }
      ]
    };
  }
};
</script>

In the code above, we have the values array, which is used as the data for our sorted-table component. Then we add the table rows by using the regular HTML tr element.

In the table header, we add the sort-link component to each th element to let us sort each column individually.

We can also add icons for the up and down arrows used for the sort-link by passing in a second argument info Vue.use as follows:

Vue.use(SortedTablePlugin, {
  ascIcon: '<i class="material-icons">arrow_drop_up</i>',
  descIcon: '<i class="material-icons">arrow_drop_down</i>'
});

Also, the objects containing the values have to be a flat object. Other optional available include values , dir , sort , ascIcon , descIcon ,onSort . values is an array of objects containing the table values. dir is the sort direction, sort is the default sorting column, ascIcon and descIcon are the icons for the sort arrows, and onSort is a callback for custom sorting.

Conclusion

We can add tables easily with Vue Handsontable and vue-sorted-table . Vue Handsontable is more full-featured and works like a spreadsheet with its ability to edit cells and add/remove columns. vue-sorted-table is simpler. Its only purpose is to provide sorting on table columns.

Categories
JavaScript Vue

Add a Conditional Class to a Vue Component

We can conditionally add classes to a Vue component by using the v-bind:class directive. The shorthand for that is :class.

For instance, we can add it as follows:

<template>
  <div id="app">
    <button @click="isRed = !isRed">Toggle</button>
    <div :class="{red: isRed, green: !isRed}">foo</div>
  </div>
</template>

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

<style>
.red {
  color: red;
}

.green {
  color: green;
}
</style>

In the code above, we have:

:class="{red: isRed, green: !isRed}"

to set the class according to the value of isRed. Since it’s false initially, the green class will be applied. Then when we click the Toggle button for the first, isRed becomes true, so the red class will be applied.

In the style section, we specified that the red class has color red and green class has color green, so the div’s text will toggle between red and green as we click the button.

We can move the object to a computed property so that our template won’t have too much code. To do that we can write the following:

<template>
  <div id="app">
    <button @click="isRed = !isRed">Toggle</button>
    <div :class="classObj">foo</div>
  </div>
</template>

<script>
export default {
  name: "App",
  computed: {
    classObj() {
      return { red: this.isRed, green: !this.isRed };
    }
  },
  data() {
    return { isRed: false };
  }
};
</script>

<style>
.red {
  color: red;
}

.green {
  color: green;
}
</style>

We moved the object that passed into the :class directive to the function inside the computed property as follows:

classObj() {
  return { red: this.isRed, green: !this.isRed };
}

The value of classObj will update when this.isRed is updated, so we’ll get the same result as before.

In both examples, we have one conditional class applied to the div in our Vue component at one time.

Array Syntax

We can also define an array of classes, with the class names as the entries of the array. The condition for which the class is applied will be in the data object as the value of the properties with the given class names.

For instance, we can write the following code to do that:

<template>
  <div id="app">
    <button @click="isRed = !isRed">Toggle</button>
    <div :class="[isRed ? red: '', !isRed ? green: '']">foo</div>
  </div>
</template>

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

<style>
.red {
  color: red;
}

.green {
  color: green;
}
</style>

In the code above, we have:

{ isRed: false, red: "red", green: "green" }

to place the class names as variables. Then we conditionally apply them by writing:

[isRed ? red: '', !isRed ? green: '']

in the template. Therefore, we’ll see the same result as before since the conditions and classes are the same as before. It’s just that we used the array syntax instead of the object syntax.

Conditionally Applying Classes With Vue Components

We can apply the :class directive directly on our own components or 3rd party ones. To do that, we use the same syntax. For instance, we can write the following code to do that:

components/Foo.vue:

<template>
  <p>foo</p>
</template>

App.vue:

<template>
  <div id="app">
    <button @click="isRed = !isRed">Toggle</button>
    <Foo :class="[isRed ? red: '', !isRed ? green: '']"/>
  </div>
</template>

<script>
import Foo from "./components/Foo.vue";

export default {
  name: "App",
  components: {
    Foo
  },
  data() {
    return { isRed: false, red: "red", green: "green" };
  }
};
</script>

<style>
.red {
  color: red;
}

.green {
  color: green;
}
</style>

The classes we applied conitionally will still be applied to the roo element of Foo automatically.

We can also do the same with the object syntax as follows:

App.vue:

<template>
  <div id="app">
    <button @click="isRed = !isRed">Toggle</button>
    <Foo :class="classObj"/>
  </div>
</template>

<script>
import Foo from "./components/Foo.vue";

export default {
  name: "App",
  components: {
    Foo
  },
  computed: {
    classObj() {
      return { red: this.isRed, green: !this.isRed };
    }
  },
  data() {
    return { isRed: false, red: "red", green: "green" };
  }
};
</script>

<style>
.red {
  color: red;
}

.green {
  color: green;
}
</style>

They both get the same results.

Conclusion

We can apply a class conditionally with the :class or v-bind:class directive. We can set the value of it as an object or an array.

To make our template cleaner, we can put our class code in a computed property so that it’ll be updated when any piece of component data updates.

A conditional class can be applied to elements and components alike.

Categories
JavaScript Vue

Watch Input Change with Vue.js

We can watch for input value changes with Vue.js with the watch property.

Add a Watcher

To do this, we can add the watch property to our component. We can write the following to check watch for the inputted value of a model and do something to it as follows:

<template>
  <div id="app">
    <input v-model="value">
    <p>{{inputted}}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      value: "",
      inputted: ""
    };
  },
  watch: {
    value(val) {
      this.inputted = `Inputted: ${val}`;
    }
  }
};
</script>

In the code above, we have the watch property that has the value method, which watches the value of the data state.

The v-model directive binds our inputted value to this.value, so this.value will always get the latest inputted value from the input.

The name of the state and the method name in watch have to match. Then we can get the val parameter and then set the this.inputted field as follows:

this.inputted = `Inputted: ${val}`;

Then we’ll see what we entered with Inputted: added before it.

Conclusion

We can add a watcher with the watch property. Then we can use that to update other values as the given value changes.

Categories
JavaScript Vue

Watch Vuex Store State Change in a Vue.js App

We can easily watch for store Vuex store changes in a Vue.js app by adding computed properties or using getters.

In this article, we’ll look at how to do watch the Vuex store state with both ways.

Computed Properties

We can use computed properties to watch for the latest value from the store and return it.

For instance, we can write the following code to create a store and then access the value in a component:

main.js:

import Vue from "vue";
import App from "./App.vue";
import Vuex from "vuex";
Vue.use(Vuex);

Vue.config.productionTip = false;

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  }
});

new Vue({
  store,
  render: h => h(App)
}).$mount("#app");

App.vue:

<template>
  <div id="app">
    <button @click="increment">Increment</button>
    <p>{{count}}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  computed: {
    count() {
      return this.$store.state.count;
    }
  },
  methods: {
    increment() {
      this.$store.commit("increment");
    }
  }
};
</script>

In the code above, we have the the store in main.js which holds the count state.

We put the store in our Vue instance. Then in App.vue, we reference the store by using this.$store.

Then we can access the count state we did in the count method in the computed property.

In the end, we see the latest count displayed on the screen as we click the Increment button to call increment, which commits a new value to the store.

Getters

We can create a getter in the store and then use the mapGetters method to add the getter as a computed property in our component. For instance, we an write the following to do that:

main.js:

import Vue from "vue";
import App from "./App.vue";
import Vuex from "vuex";
Vue.use(Vuex);

Vue.config.productionTip = false;

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  getters: {
    count: state => {
      return state.count;
    }
  }
});

new Vue({
  store,
  render: h => h(App)
}).$mount("#app");

App.vue:

<template>
  <div id="app">
    <button @click="increment">Increment</button>
    <p>{{count}}</p>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
  name: "App",
  computed: {
    ...mapGetters(["count"])
  },
  methods: {
    increment() {
      this.$store.commit("increment");
    }
  }
};
</script>

In the code above, we added a getter in our store with:

getters: {
  count: state => {
    return state.count;
  }
}

in main.js. Then in the script section of App.vue, we have:

import { mapGetters } from "vuex";
export default {
  name: "App",
  computed: {
    ...mapGetters(["count"])
  },
  methods: {
    increment() {
      this.$store.commit("increment");
    }
  }
};

We imported the mapGetters method from vuex to add the getter directly as a computed property.

In the array we passed into mapGetters we pass in the getter name from the store to access the returned value from the getter.

Therefore, we’ll see the same result as before.

Conclusion

Computed properties are good for getting some simple states. If we need to derive states from a given state, then we should use getters with the mapGetters method to map them to computed properties.

Categories
JavaScript Vue

Introduction to Bootstrap Vue

BootstrapVue is the Vue version of Bootstrap. Like the plain JavaScript version of Bootstrap, it has many kinds of elements to let us style our page and make them look good.

BoostrapVue has the same elements, but they’re all available as Vue components. Therefore, we can add them straight into our Vue app without much hassle.

In this article, we’ll look at how use BootstrapVue in our Vue app to make it look good.

Getting Started

Getting started with BootstrapVue is easy. We need Vue 2.6 in our app but Vue 2.6.11 is recommended. At least Bootstrap 4.3.1 is required. Also, PortalVue 2.1 is required by Toasts.

To install it, we run:

npm install vue bootstrap-vue bootstrap

Then we register the BootstrapVue library in our app so we can use the components and directives in our app’s components.

Assuming that we used the Vue CLI to generate our Vue project, we add the following code register the BootstrapVue libraries in our app:

main.js:

import Vue from "vue";
import App from "./App.vue";
import { BootstrapVue, IconsPlugin } from "bootstrap-vue";
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.use(BootstrapVue);
Vue.use(IconsPlugin);

Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

In the code above, we imported the CSS and the called Vue.use to register BootstrapVue for the core library and IconsPlugin for the icons.

To register individual components and directives manually, we can write the following in the entry point file of our Vue app:

Vue.component('b-modal', BModal)
Vue.directive('b-modal', VBModal)

The individual components of the BootstrapVue library can also be imported individually into our app. For instance, if we only want to include the Bootstrap modal in our app, we write:

import { ModalPlugin } from 'bootstrap-vue'
Vue.use(ModalPlugin)

in the same file.

We can also import the component straight into our component if we want to use them in our component. For instance, we can write:

import { BModal, VBModal } from 'bootstrap-vue'

Vue.component('modal-component', {
  components: {
    'b-modal': BModal
  },
  directives: {
    'b-modal': VBModal
  }
})

to import the modal from BootstrapVue and then register them in our component so that we can use them.

Basic Form Controls

One of the common components in a web app are probably forms and the corresponding inputs. BootstrapVue has form controls that are commonly used like text inputs, checkboxes, files inputs, radio buttons, dropdowns, etc.

To make a simple form with BootstrapVue, we can write the following:

App.vue:

<template>
  <div id="app">
    <b-form @submit.prevent="onSubmit" @reset="onReset">
      <b-form-group label="Name:" description="Enter your name" id="name">
        <b-form-input
          id="name-group"
          v-model="form.name"
          type="text"
          required
          placeholder="Enter name"
        ></b-form-input>
      </b-form-group>

      <b-form-group id="email-group" label="Email:" label-for="email">
        <b-form-input id="email" v-model="form.email" required placeholder="Enter email"></b-form-input>
      </b-form-group>

      <b-form-group id="fruit-group" label="Fruit:" label-for="favorite-fruit">
        <b-form-select id="favorite-fruit" v-model="form.fruit" :options="fruits" required></b-form-select>
      </b-form-group>

      <b-form-group id="sign-up">
        <b-form-checkbox-group v-model="form.choices" id="sign-up">
          <b-form-checkbox value="foo">I want foo</b-form-checkbox>
          <b-form-checkbox value="bar">I want bar</b-form-checkbox>
        </b-form-checkbox-group>
      </b-form-group>

      <b-button type="submit" variant="primary">Submit</b-button>
      <b-button type="reset" variant="danger">Reset</b-button>
    </b-form>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      fruits: ["apple", "orange", "banana"],
      form: {}
    };
  },
  methods: {
    onSubmit(){
      console.log(this.form)
    },
    onReset(){
      alert('Form reset')
    }
  }
};
</script>

In the code above, we wrap our controls in the b-form-group component, which corresponds to the form group in the plain JavaScript version of Bootstrap. Inside each b-form-group, we have our form control. If it’s a text input, then we use the b-form-input component. It takes the v-model directive to bind the input value to the model.

The b-form-select component is a dropdown. It takes the options prop, which binds to an array of values and display them in the dropdown as the choices. v-model binds to the selected choice.

The b-form-checkbox component renders the checkbox control. They reside inside the b-form-checkbox-group component, which takes the v-model directive that binds to an array of the checked choices.

b-buttons are render buttons. We can set the style with the variant prop. It also takes the type prop, which sets the type attribute of the button.

All of them items above are wrapped inside the b-form component. It handles the submit event and reset event just like a regular HTML form. In the code above, we have the @submit.prevent directive to prevent the default submit action, so it’ll run onSubmit and log the value.

The onReset handler runs when we click Reset to reset the form.

Inline form

We can add the inline prop on b-form to display form controls and buttons on a single horizontal row.

For instance, we can make a form with an inline input, checkbox and button as follows:

<template>
  <div id="app">
    <b-form inline>
      <label class="sr-only" for="name">Name</label>
      <b-input-group class="mb-2 mr-sm-2 mb-sm-0">
        <b-input id="name" placeholder="Name" v-model='form.name'></b-input>
      </b-input-group>

      <b-form-checkbox class="mb-2 mr-sm-2 mb-sm-0">Remember me</b-form-checkbox>

      <b-button variant="primary">Save</b-button>
    </b-form>
  </div>
</template>

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

All we did was add inline to the b-form as an attribute. Then everything inside is inline.

Form Validation Feedback

The b-form-invalid-feedback component lets us add feedback when an invalid inputs are entered into an input. There’s also a b-form-valid-feedback to indicate that a valid value is inputted into the input box.

For instance, we can use it as follows:

<template>
  <div>
    <b-form @submit.stop.prevent>
      <label for="email">Email</label>
      <b-input v-model="form.email" :state="validation" id="email-user"></b-input>
      <b-form-invalid-feedback :state="validation">Email not valid.</b-form-invalid-feedback>
      <b-form-valid-feedback :state="validation">Email is valid.</b-form-valid-feedback>
    </b-form>
  </div>
</template>

<script>
export default {
  name: "App",
  computed: {
    validation(){
      return /^\S+@\S+$/.test(this.form.email)
    }
  },
  data() {
    return {
      form: {}
    };
  }
};
</script>

In the code above, we have an input which takes an email. We use a computed property to compute the validity of the inputted text to see if it’s actually an email address. This computation is done in the validation function.

The resulting validation computed property is set as the value of the state prop. Then if validation returns true we display the b-form-valid-feedback component. Otherwise, we display the b-form-invalid-feedback component.

The b-input component also takes the state prop with the value set to validation. The border and icon on the right changes depending if the input is valid. If validation returns true, which means the inputted value is valid, then the border turns green and a check mark icon is displayed. Otherwise, the border turns red and an exclamation mark icon is displayed.

If we don’t want to display any validation feedback and we have the state prop added onto the components, we can set the value to null.

Radio Button

We can use the b-form-group with the b-form-radio-group nested inside to create a group of radio buttons. b-form-radio-group takes the options prop which is the options for the radio button group. It also takes the v-model directive to bind the radio value that’s selected to the model.

For example, we can add the radio button as follows:

<template>
  <div>
    <b-form-group label="Favorite Fruit">
      <b-form-radio-group
        id="radio-group"
        v-model="selected"
        :options="options"
        name="radio"
      ></b-form-radio-group>
    </b-form-group>
    <p>{{selected}}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      selected: "apple",
      options: [
        { text: "apple", value: "apple" },
        { text: "orange", value: "orange" },
        { text: "banana", value: "third", disabled: true },
        { text: "grape", value: { name: 'grape' } }
      ]
    };
  }
};
</script>

In the code above, we have an options array with the data for the choices. The text property will be displayed to the user as the text for each choice. The value will be the selected value. It doesn’t matter what kind of object or value it is. As we can see, anything works.

When we click the value, we get the value selected set as the value of selected.

Images

Bootstrap has the b-img component for displaying images. It’s useful because it makes images responsive so they won’t be larger than their parent elements.

We can use it as follows:

<template>
  <div>
    <b-img
      src="https://images.unsplash.com/reserve/bOvf94dPRxWu0u3QsPjF_tree.jpg?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=755&q=80"
      fluid
      alt="tree"
    ></b-img>
  </div>
</template>

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

The code above creates a responsive image automatically. It also takes an alt attribute like a regular img element for accessibility.

We can also change fluid to fluid-grow so that the image fills the screen’s width if it’s smaller than width of the screen.

It also has a feature to round the corner of images. To make an image with rounded corners, we can add the rounded prop to the b-img component. If we don’t pass in any value, then all corners are rounded.

We can also set the values as follows:

  • true or no value: round all corners
  • false or prop not present: no rounding or corners (default)
  • 'top': round the top corners
  • 'right': round the right corners
  • 'bottom': round the bottom corners
  • 'left': round the left corners
  • 'circle': make a circle (if square image) or oval (if not square) border
  • '0': turn off rounding of corners

We can make an oval image as follows:

<template>
  <div>
    <b-img
      src="https://images.unsplash.com/reserve/bOvf94dPRxWu0u3QsPjF_tree.jpg?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=755&q=80"
      fluid
      rounded='circle'
      alt="tree"
    ></b-img>
  </div>
</template>

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

Tables

Tables are an important part of many apps. Therefore, like the regular version of Bootstrap, BootstrapVue also has a table component built in.

We can create a table by using the b-table component. Then we don’t have to create a table from scratch. For instance, we can create a table with some data and an explicit mapping of table fields to the headings by writing:

<template>
  <div>
    <b-table striped hover :items="items" :fields='fields'></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      fields: [
        { key: "firstName", label: "First" },
        { key: "lastName", label: "Last" },
        "age",
      ],
      items: [
        { age: 38, firstName: "Jane", lastName: "Smith" },
        { age: 21, firstName: "Alex", lastName: "May" },
        { age: 16, firstName: "Mary", lastName: "Jones" },
      ]
    };
  }
};
</script>

In the code above, we have the fields object, which has the key, which is the property names of the items entries. The label is the heading text of the column of the corresponding field name. So firstName in the item from the items entry corresponds has the First heading. The lastName in the item from the items entry has the Last heading.

Modals

Modals are also an important part of many apps. We need them to overlay the page for dialog boxes and other similar things.

BootstrapVue has the b-modal component to make creating modal dialogs easy. We just need to set the id prop of the b-modal and then we use the id name as the v-b-modal‘s directive modifier on the element that’ll open when the element is clicked so that the element will open the modal with the id that we set.

The title is set so that we can set the title of the modal.

For instance, we can write the following to show the modal when a button is clicked:

<template>
  <div>
    <b-button v-b-modal.modal-simple>Show modal</b-button>

    <b-modal id="modal-simple" title="Simple Modal">
      <p>Hello!</p>
    </b-modal>
  </div>
</template>

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

In the code above, we have the v-b-modal.modal-simple directive on the button to show the modal with the id. Then the modal will show ‘Simple Modal’ as the title once it’s opened.

The modal also has the OK and Cancel button by default.

Conclusion

With BootstrapVue, we can create a Vue app that has styled components fast. It has components for form controls, tables, images, and many more that aren’t shown in this article. It’s easy to use and so we can get results fast.

To components also lets us write cleaner code. As we can see from the b-table example, we didn’t have to reference the table elements at all to create a table. We just need the data and the b-table component will map the fields to table cells.