Categories
BootstrapVue

BootstrapVue — Navigation

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 navigation components.

Navs

BootstrapVue comes with a b-nav component to let us add a navigation bar to our app.

For example, we can write:

<template>
  <div id="app">
    <b-nav>
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-item disabled>baz</b-nav-item>
    </b-nav>
  </div>
</template>

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

We have the b-nav component, which has b-nav-item components inside.

The active prop makes a nav item active.

disabled makes it grayed out and not clickable.

Tab Style

We can add the tabs prop to make the navbar look like tabs.

For instance, we can write:

<template>
  <div id="app">
    <b-nav tabs>
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-item disabled>baz</b-nav-item>
    </b-nav>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Now the active tab has lines surrounding it.

The rest is the same.

Pill Style

The pills prop makes the nav items look like buttons.

For example, we can write:

<template>
  <div id="app">
    <b-nav pills>
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-item disabled>baz</b-nav-item>
    </b-nav>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Small Size

We can make the nav items smaller than the default with the small prop:

<template>
  <div id="app">
    <b-nav small>
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-item disabled>baz</b-nav-item>
    </b-nav>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Fill

The fill prop makes the nav extends to its full width:

<template>
  <div id="app">
    <b-nav fill>
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-item disabled>baz</b-nav-item>
    </b-nav>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Justified

The justified prop lets us make nav items equal width and the nav occur al horizontal space:

<template>
  <div id="app">
    <b-nav justified>
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-item disabled>baz</b-nav-item>
    </b-nav>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Alignment

We can add the align prop to align the nav items the way we like.

The value can be left , center , or right .

For example, we can write:

<template>
  <div id="app">
    <b-nav align="right">
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-item disabled>baz</b-nav-item>
    </b-nav>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Since we set align to 'right' , we have the nav items on the right.

Vertical Variation

The navbar can be made vertical with the vertical prop:

<template>
  <div id="app">
    <b-nav vertical>
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-item disabled>baz</b-nav-item>
    </b-nav>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Dropdowns

We can add dropdowns into the navbar.

To do that, we use the b-nav-item-dropdown component:

<template>
  <div id="app">
    <b-nav>
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-item-dropdown text="fruit" toggle-class="nav-link-custom" right>
        <b-dropdown-item>apple</b-dropdown-item>
        <b-dropdown-divider></b-dropdown-divider>
        <b-dropdown-item>banana</b-dropdown-item>
      </b-nav-item-dropdown>
    </b-nav>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

We just put the b-nav-item-dropdown component into the b-nav and we get a dropdown displayed.

Text Content

We can add text content to a navbar with the b-nav-text component:

<template>
  <div id="app">
    <b-nav>
      <b-nav-item active>foo</b-nav-item>
      <b-nav-item>bar</b-nav-item>
      <b-nav-text>text</b-nav-text>
    </b-nav>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Conclusion

We can add navbars to an app with the b-nav component.

The b-nav-item is an item that’s shown inside the navbar.

We can also add dropdown and forms inside the navbar.

Categories
BootstrapVue

BootstrapVue — Radio Inputs

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 radio button inputs.

Radio Buttons

BootstrapVue comes with the b-form-radio-group component to let us add radio buttons to our forms.

For example, we can write:

<template>
  <div id="app">
    <b-form-radio v-model="selected" name="fruit" value="apple">apple</b-form-radio>
    <b-form-radio v-model="selected" name="fruit" value="orange">orange</b-form-radio>
    <p>{{selected}}</p>
  </div>
</template>

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

We have 2 radio buttons with the same name attribute value and binds to the same state.

Therefore, when we click a button, the selected state will update.

Grouped Radios

We can group them together by using the b-form-radio-group component.

This way, we don’t have to add each radio button individually.

For example, we can write:

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

<script>
export default {
  name: "App",
  data() {
    return {
      selected: "",
      options: [
        { text: "Apple", value: "apple" },
        { text: "Orange", value: "orange" }
      ]
    };
  }
};
</script>

Then we can specify all the radio buttons in one component.

options has the options we want to render.

selected is the state we want to bind the value to.

We can mix and match the options prop and b-form-radio components in b-form-radio-group .

For example, we can write:

<template>
  <div id="app">
    <b-form-radio-group
      id="radio-slots"
      v-model="selected"
      :options="options"
      name="radio-options-slots"
    >
      <template v-slot:first>
        <b-form-radio value="grape">Grape</b-form-radio>
      </template>

      <b-form-radio :value="{ banana: 'banana' }">Banana</b-form-radio>
    </b-form-radio-group>
    <p>{{selected}}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      selected: "",
      options: [
        { text: "Apple", value: "apple" },
        { text: "Orange", value: "orange" }
      ]
    };
  }
};
</script>

We added various kinds of radio buttons.

We have Apple and Orange added by specifying the options prop.

Banana is specified with the value prop.

And we added a template to add the Grape option. We specify that we want to populate the first slot, so it’ll appear first.

Now we’ll see the options when we click the buttons.

We can also add HTML content to the label with the html property.

Instead of the text property, we use the html property.

However, this may make our app vulnerable to cross-site scripting attacks since the text isn’t sanitized.

We can write:

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

<script>
export default {
  name: "App",
  data() {
    return {
      selected: "",
      options: [
        { html: "<b>Apple</b>", value: "apple" },
        { text: "Orange", value: "orange" }
      ]
    };
  }
};
</script>

Changing Option Field Names

The field property names can change according to our preference.

There’s the text-field prop that takes a property name of the option objecrt to display as the label text.

And the value-field prop lets us set the property name for the value field.

For instance, we can write:

<template>
  <div id="app">
    <b-form-radio-group
      v-model="selected"
      :options="options"
      value-field="item"
      text-field="name"
      name="fruits"
    >
    </b-form-radio-group>
    <p>{{selected}}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      selected: "",
      options: [
        { name: "Apple", item: "apple" },
        { name: "Orange", item: "orange" }
      ]
    };
  }
};
</script>

then we change the field names with the props.

name is displayed and item is set as the value of selected .

Stacked or Inline

We can take our radio button group stacked or line.

By default, it’s inline.

We can add the stacked prop to make them stacked.

For example, we can write:

<template>
  <div id="app">
    <b-form-radio-group
      v-model="selected"
      :options="options"
      stacked
      name="fruits"
    >
    </b-form-radio-group>
    <p>{{selected}}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      selected: "",
      options: [
        { text: "Apple", value: "apple" },
        { text: "Orange", value: "orange" }
      ]
    };
  }
};
</script>

and now they’re stacked.

Conclusion

We can create radio buttons individually or as a group.

As long as the name value of each is the same, we can bind it to the same state field.

There are also many other customization options with labels and text.

Categories
BootstrapVue

BootstrapVue — Layouts

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 layouts.

Variable Width Content

We can set a breakpoint prop to 'auto' to make the column variable.

Breakpoints include xs, sm , md , and lg and xl .

xs is smaller than 576px wide.

sm is bigger than or equal to 576px wide.

md is bigger than or equal to 768px wide.

lg is bigger than or equal to 992px wide.

xl is bigger than or equal to 1200px wide.

For instance, we can write:

<template>
  <div id="app">
    <b-container>
      <b-row>
        <b-col col >1</b-col>
        <b-col col sm="auto">2</b-col>
        <b-col col >3</b-col>
      </b-row>
    </b-container>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

to make the middle column variable width.

We added the col and sm='auto' to make the middle column variable width and the other columns fill the remaining space.

Responsive Classes

We can use the cols prop to adjust the column width proportion.

The value should be between 1 and 12.

For example, we can write:

<template>
  <div id="app">
    <b-container>
      <b-row>
        <b-col cols="8">8</b-col>
        <b-col cols="4">4</b-col>
      </b-row>
    </b-container>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Then we have the left column taking 8 / 12 or two-thirds of the space.

The right column takes 4 / 12 or a third of the space.

Stacked to Horizontal

We can use the sm prop to create a grid that’s stacked on small devices and becoming horizontal of medium devices.

For example, we can write:

<template>
  <div id="app">
    <b-container>
      <b-row>
        <b-col sm="8">8</b-col>
        <b-col sm="4">4</b-col>
      </b-row>
    </b-container>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Then on a narrow screen, the 8 is above the 4, while on wider screens they’re side by side.

Alignment

We can use the align-v prop on b-row to vertical-align the content.

For example, we can write:

<template>
  <div id="app">
    <b-container>
      <b-row align-v="center">
        <b-col>1</b-col>
        <b-col>2</b-col>
      </b-row>
    </b-container>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

<style>
.row {
  height: 200px;
}
</style>

Then the row is centered in the b-row .

Other possible values of align-v can be 'start' to align the rows to the top edge.

Also, we can set it to 'end' to align the rows to the bottom edge.

'baseline' aligns the tallest row to the top edge.

And 'stretch' stretches the height to the height of the container.

Horizontal Alignment

To horizontally align items, we can use the align-h prop to do that.

For example, we can write:

<template>
  <div id="app">
    <b-container>
      <b-row align-h="start">
        <b-col cols="4">1</b-col>
        <b-col cols="4">2</b-col>
      </b-row>
    </b-container>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

We used the align-h prop to align the items to the left with the value 'start'

Other values includes 'center' , which aligns content to the center.

'end' align contents to the right.

'around' spreads the content horizontally.

'between' put the content near the edges.

Ordering Columns

We can use the order-* prop to control the visual order of our content.

These props are responsive.

For instance, we can write:

<template>
  <div id="app">
    <b-container>
      <b-row>
        <b-col order="2">foo</b-col>
        <b-col order="1">bar</b-col>
      </b-row>
    </b-container>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Because of the order prop, the ‘foo’ div is to the right of the ‘bar’ div.

We can write order-md , order-sm , etc. to change the order only when those breakpoints are hit.

Conclusion

There are many ways to size columns.

We can change the size according to breakpoint so we can have responsive layouts.

We can add spaces wherever we want as well.

Categories
BootstrapVue

BootstrapVue — Customizing Form Tags

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 form tags.

Custom Rendering of Tags

We can customize the rendering of the tags.

To do that, we use the slot.

For instance, we can write:

<template>
  <div id="app">
    <b-form-tags v-model="value" no-outer-focus class="mb-2">
      <template v-slot="{ tags, inputAttrs, inputHandlers, addTag, removeTag }">
        <b-input-group aria-controls="my-custom-tags-list">
          <input
            v-bind="inputAttrs"
            v-on="inputHandlers"
            placeholder="add tag"
            class="form-control"
          >
          <b-input-group-append>
            <b-button [@click](http://twitter.com/click "Twitter profile for @click")="addTag()" variant="primary">Add</b-button>
          </b-input-group-append>
        </b-input-group>
        <ul>
          <b-card v-for="tag in tags" :key="tag" tag="li">
            <strong>{{ tag }}</strong>
            <b-button [@click](http://twitter.com/click "Twitter profile for @click")="removeTag(tag)" variant="link" size="sm">remove</b-button>
          </b-card>
        </ul>
      </template>
    </b-form-tags>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      value: ["apple"]
    };
  }
};
</script>

We have an input box.

The slot has the addTag and removeTag methods to add and remove the tags.

The inputAttrs let us bind the input tag to inputAttrs .

inputHandlers is run when we enter a tag.

addTag is run when we click Add.

removeTag is run when we click the remove button on the tag.

We have the b-card component which is displayed as an li element to display the entered tags.

Custom Form Components

We can also use the b-form-tag component to display our tags outside the input.

For instance, we can write:

<template>
  <div id="app">
    <b-form-tags v-model="value" no-outer-focus class="mb-2">
      <template v-slot="{ tags, inputAttrs, inputHandlers, addTag, removeTag }">
        <b-input-group aria-controls="my-custom-tags-list">
          <input
            v-bind="inputAttrs"
            v-on="inputHandlers"
            placeholder="add tag"
            class="form-control"
          >
          <b-input-group-append>
            <b-button @click="addTag()" variant="primary">Add</b-button>
          </b-input-group-append>
        </b-input-group>
        <b-form-tag v-for="tag in tags" [@remove](http://twitter.com/remove "Twitter profile for @remove")="removeTag(tag)" :key="tag" :title="tag">{{ tag }}</b-form-tag>
      </template>
    </b-form-tags>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      value: ["apple"]
    };
  }
};
</script>

We have the b-form-tag component to display the items outside the input element.

Also, we can make the b-form-tags component display as a select box.

For instance, we can write:

<template>
  <div id="app">
    <b-form-tags v-model="value" add-on-change>
      <template v-slot="{ tags, inputAttrs, inputHandlers, disabled, removeTag }">
        <ul v-if="tags.length > 0" class="list-inline d-inline-block mb-2">
          <li v-for="tag in tags" :key="tag">
            <b-form-tag
              [@remove](http://twitter.com/remove "Twitter profile for @remove")="removeTag(tag)"
              :title="tag"
              :disabled="disabled"
              variant="info"
            >{{ tag }}</b-form-tag>
          </li>
        </ul>
        <b-form-select
          v-bind="inputAttrs"
          v-on="inputHandlers"
          :disabled="availableOptions.length === 0"
          :options="availableOptions"
        >
          <template v-slot:first>
            <option disabled value>Choose one...</option>
          </template>
        </b-form-select>
      </template>
    </b-form-tags>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      options: ["apple", "orange", "grape"],
      value: ["apple"]
    };
  },
  computed: {
    availableOptions() {
      return this.options.filter(opt => !this.value.includes(opt));
    }
  }
};
</script>

We have the b-form-tags component, which has a template nested in it to let us display tags the way we like.

Like the previous example, we use the variables and methods from the slots.

Also, we have the b-form-select component to display the items that can be selected.

We have the ‘Choose one…’ placeholder.

In the b-form-select component.

We have the disabled prop to disable the select element when we have availableOptions has no options left.

availableOptions is a computed property that’s computed from the options array.

We filter out the ones that already have been selected.

The add-on-change prop on the b-form-tags component will let us add the tag if an item is selected from the dropdown.

We can also add any custom input component that emits the input and change events into the input template.

For example, we can write:

<template v-slot:default="{ inputAttrs, inputHandlers, removeTag, tags }">
  <custom-input
    :id="inputAttrs.id"
    :vistom-value-prop="inputAttrs.value"
    @custom-input-event="inputHandlers.input($event)"
    @custom-change-event="inputHandlers.change($event)"
    @keydown.native="inputHandlers.keydown($event)"
  ></custom-input>
  <template v-for="tag in tags">
    <!-- Your custom tag list here -->
  </template>
</template>

Conclusion

We can customize our form tag input in many ways.

We can change the input element.

Also, we can change how the inputted tags are displayed.

The slot provides the methods to add or remove the tags.

Categories
BootstrapVue

BootstrapVue — Radio Input Customization and Star Rating

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 radio button inputs and create a star rating input.

Sizing

The size prop lets us change the size.

For example, we can write:

<template>
  <div id="app">
    <b-form-radio name="size" size="sm">Small</b-form-radio>
  </div>
</template>

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

and make our radio button small.

We can also set it to 'lg' to make it big.

Button Style Radio Buttons

We can make the radio buttons look like a button.

For instance, we can write:

<template>
  <div id="app">
    <b-form-radio-group v-model="selected" :options="options" buttons name="radios"></b-form-radio-group>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      selected: "",
      options: [
        { text: "Apple", value: "apple" },
        { text: "Orange", value: "orange" }
      ]
    };
  }
};
</script>

We added the buttons prop to make them look like buttons.

The selected option will look like it’s pressed down.

Render as Native Radio Buttons

We can render radio buttons as native radio buttons with the plain prop.

For instance, we can write:

<template>
  <div id="app">
    <b-form-radio-group plain v-model="selected" :options="options" name="radios"></b-form-radio-group>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      selected: "",
      options: [
        { text: "Apple", value: "apple" },
        { text: "Orange", value: "orange" }
      ]
    };
  }
};
</script>

Then there will be no Bootstrap styling applied to them.

Display Validation State

To display the validate state, we can add the state prop.

For example, we can write:

<template>
  <div id="app">
    <b-form-radio-group :state="state" v-model="selected" :options="options" name="radios"></b-form-radio-group>
    <b-form-invalid-feedback :state="state">please choose one</b-form-invalid-feedback>
    <b-form-valid-feedback :state="state">looks good</b-form-valid-feedback>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      selected: "",
      options: [
        { text: "Apple", value: "apple" },
        { text: "Orange", value: "orange" }
      ]
    };
  },
  computed: {
    state() {
      return this.selected.length > 0;
    }
  }
};
</script>

We have the state computed property which checks if the selected state is populated with the choices.

Then we set that as the state prop’s value for b-form-invalid-feedback and b-form-valid-feedback .

Now when we click on a choice, we’ll see everything displayed in green, including the validation message.

On the other hand, if we didn’t select anything, then everything is displayed in red.

Form Rating

If we want to add a star rating input when we can use the b-form-rating component.

This is a new component that’s available since 2.12.0.

For instance, we can use it by writing:

<template>
  <div id="app">
    <b-form-rating v-model="value"></b-form-rating>
    <p>{{ value }}</p>
  </div>
</template>

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

We just add the component and use v-model to set the inputted value to the state we want.

Then we show the value .

Read-Only Rating

The readonly prop can be added to the component.

For instance, we can write:

<template>
  <div id="app">
    <b-form-rating v-model="value" readonly></b-form-rating>
  </div>
</template>

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

and we’ll see 4 stars. We can’t change its value.

Rating Styling

We can use the variant prop to change its styling.

For example, we can write:

<template>
  <div id="app">
    <b-form-rating v-model="value" variant="success"></b-form-rating>
  </div>
</template>

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

Then the stars are green.

Other possible values for variant include 'warning' , 'success' , 'danger' , 'primary' , and 'info' .

To change the stars to other colors, we can use the color prop.

For instance, we write:

<template>
  <div id="app">
    <b-form-rating v-model="value" color="indigo"></b-form-rating>
  </div>
</template>

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

Then the stars will be indigo.

Conclusion

We can change the size of the radio button inputs. The radio buttons can also be displayed as buttons.

Also, we can add validation state display to radio button groups.

We can also add a start rating input component to let users set rating scores.