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.

Categories
BootstrapVue

BootstrapVue — Jumbotrons and 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 jumbotrons. We also look at how to create basic layouts.

Customizing Jumbotrons

We can add HTML content into a jumbotron by populating slots.

For example, we can write:

<template>
  <div id="app">
    <b-jumbotron>
      <template v-slot:header>Hello</template>

      <template v-slot:lead>Lead</template>

      <p>World</p>
      <b-button variant="primary" href="#">Go Somewhere</b-button>
    </b-jumbotron>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

We added the template tags.

And we have the v-slot directives to populate different slots.

header lets us set the header contents.

lead lets us set the lead content, which is displayed below the header .

Header and Lead Tags

We can change the header and lead tags with the header-tag and lead-tag props.

For instance, we can write:

<template>
  <div id="app">
    <b-jumbotron header="Hello" lead="Lead" header-tag="h2" lead-tag="p">
      <p>World</p>
      <b-button variant="primary" href="#">Go Somewhere</b-button>
    </b-jumbotron>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Now we set the header and lead tags to h2 and p respectively.

Styling Variants

We can change the styling by using the bg-variant prop to change the background.

It can take the values info , danger , warning , light and dark .

The border can set with the border-variant prop. And the text style can ve set with the text-variant prop.

For instance, we can write:

<template>
  <div id="app">
    <b-jumbotron text-variant='light' bg-variant="info" header="Hello" lead="Lead">
      <p>World</p>
      <b-button variant="primary" href="#">Go Somewhere</b-button>
    </b-jumbotron>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Then we get white text on a green background.

Layout and Grid System

BootstrapVue has its own layout and grid components.

It comes with the b-container , b-row , and b-col components.

For example, we can write:

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

We used the b-container component to contain a b-row , and that contains 3 b-col components.

b-row is a row and b-col is a column.

We can make it responsive with the fluid prop.

Responsive Fluid Containers

The fluid prop can take on a size value that indicates on what screen size it’s 100% wide.

For instance, we can write:

<b-container fluid="sm">
  hello
</b-container>

so it’s 100% wide until the app hits the small breakpoint.

Likewise, 'md' is 100% wide until the medium breakpoint.

'lg' is 100% wide until the large breakpoint.

'xl' is 100% wide until the extra-large breakpoint.

Rows

The b-row and b-form-row components let us add rows.

b-form-row is different from b-row in that the margins of b-form-row are smaller.

Columns

We can create columns with equal without any props and the b-col component.

We can write:

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

to create them.

We can also create equal width multiline columns by adding a div with class w-100 between the columns.

For instance, if we have:

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

Then we have 2 columns on top and 2 below them.

Setting One Column Width

We can change the column width the cols prop.

For example, we can write:

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

We have cols set to 8 so that the column takes 8 / 12 of the screens’ width.

A grid is divided into 12 columns.

The other columns will fill the remaining space evenly.

Conclusion

We can add columns and rows to create responsive rows and columns.

Jumbotrons can be used to display attention-grabbing text.