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.

Categories
BootstrapVue

BootstrapVue — 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 add form tags to our forms.

Form Tags

Form tags are custom tagged input form control.

We can customize it and allow duplicate tag selection and tag validation.

To add it, we can use the b-form-tags component.

For instance, we can write:

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

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

to display an input that lets us enter tags.

v-model will bind the inputted values to an array as we can see from the p element.

When we press Enter, we’ll add the value.

We can add the no-add-on-enter prop to disable adding a new tag on entering.

And we can add tags on change with the add-on-change prop.

Tag Creation with Separators

Tag creation can be added with separators.

We can add the separator tag with all the separators we want to let users use.

For instance, we can write:

<template>
  <div id="app">
    <b-form-tags v-model="value" separator=" ,"></b-form-tags>
    <p>Value: {{ value }}</p>
  </div>
</template>

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

Then we can use the space and the comma as separators.

When we type them, we’ll see a new tag.

Last Tag Removal with Backspace

By default, the b-form-tags component doesn’t remove tags when we press backspace.

To let users press backspace to remove the last tag, we can use the remove-on-delete prop.

For example, we can write:

<template>
  <div id="app">
    <b-form-tags v-model="value" remove-on-delete></b-form-tags>
    <p>Value: {{ value }}</p>
  </div>
</template>

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

Then we can remove the last item with backspace.

Styling

We can style the tags with various props.

tag-pills renders the tags with the appearance of the pill.

tag-variant applies the styling variants built into Bootstrap.

size sets the size of the component’s appearance.

placeholder lets us set placeholder text for the input element.

state lets us set the validation state. We set it to true for valid, false for invalid or null .

disabld lets us disable the input.

For instance, we can write:

<template>
  <div id="app">
    <b-form-tags v-model="value" tag-pills size="lg"></b-form-tags>
    <p>Value: {{ value }}</p>
  </div>
</template>

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

Then the tags are more rounded and the size is bigger.

Tag Validation

We can use the tag-validator to validate the tags.

For instance, we can write:

<template>
  <div id="app">
    <b-form-tags v-model="value" :tag-validator="tagValidator"></b-form-tags>
    <p>Value: {{ value }}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      value: ["banana", "grape"]
    };
  },
  methods: {
    tagValidator(tag) {
      return tag.length > 2;
    }
  }
};
</script>

We have the tag-validator prop set to the tagValidator method.

We check that if the tag’s length is bigger than 2.

We’ll see an error message if the tag doesn’t meet that condition.

Detect New, Invalid and Duplicate Tags

We can listen to the tag-state event.

It’s emitted whenever new tags are entered into the new tag input element.

When tags don’t pass validation or duplicate tags are detected then this will also be emitted.

For instance, we can write:

<template>
  <div id="app">
    <b-form-tags v-model="tags" :tag-validator="validator" @tag-state="onTagState"></b-form-tags>
    <p>Value: {{ tags }}</p>
    <p>Invalid: {{ invalidTags }}</p>
    <p>Duplicate: {{ duplicateTags }}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      tags: [],
      validTags: [],
      invalidTags: [],
      duplicateTags: []
    };
  },
  methods: {
    onTagState(valid, invalid, duplicate) {
      this.validTags = valid;
      this.invalidTags = invalid;
      this.duplicateTags = duplicate;
    },
    validator(tag) {
      return tag.length > 2 && tag.length < 6;
    }
  }
};
</script>

We have the onTagState method that’s set as the value of the tag-state event handler.

Also, we have the validator method to set the tag-validator prop.

v-model is used to bind the inputted values to tags .

We display invalid and duplicate tags.

Then when we enter invalid or duplicate tags, they’ll be displayed in the p elements.

Conclusion

We can add the b-form-tags component to add a tags input.

It has features for validation and checking for duplicates.

Categories
BootstrapVue

BootstrapVue — Text 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 text input boxes.

Text Inputs

We can create inputs with text or other values with text, password, number, url, email, search, range, date and more.

For instance, we can add one with the b-form-input component by writing:

<template>
  <div id="app">
    <b-form-input v-model="text" placeholder="Enter your name"></b-form-input>
    <div>{{ text }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      text: ""
    };
  }
};
</script>

v-model binds the text state to the inputted value.

Then we display the text value below it.

When we type something, we’ll see it displayed below it.

Input Types

We can set it to different types.

We can set the type prop to the following values:

  • text
  • password
  • number
  • url
  • email
  • search
  • range
  • date
  • color

For instance, we can write:

<template>
  <div id="app">
    <b-form-input v-model="color" placeholder="Enter color" type="color"></b-form-input>
    <div>{{ color }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      color: ""
    };
  }
};
</script>

Then we click the input box, we see a native color picker where we can choose the color. After we pick the color, it’ll be displayed.

v-model.lazy isn’t supported by b-form-input. Instead, we should use the lazy prop for lazy evaluation.

date and time are native browser types. They aren’t customizable date pickers.

Range Type Input

We can set the type prop to range to get a slider.

For instance, we can write:

<template>
  <div id="app">
    <b-form-input v-model="value" type="range" min="0" max="5"></b-form-input>
    <div>Value: {{ value }}</div>
  </div>
</template>

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

to get a slider.

When we slide it then value is updated because of the v-model directive. We can set the steps prop to change the increment or decrement value when we slide.

For example, we can write:

<template>
  <div id="app">
    <b-form-input  v-model="value" type="range" step="0.5" min="0" max="5"></b-form-input>
    <div>Value: {{ value }}</div>
  </div>
</template>

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

Control Sizing

We can change the sizing of the controls with the size prop. The value can be sm or lg.

For instance, we can write:

<template>
  <div id="app">
    <b-form-input size="sm" placeholder="enter your name"></b-form-input>
  </div>
</template>

<script>
export default {};
</script>

Then we get an extra small input box.

Validation States

We can display green if the input value is valid. Otherwise, we can display red.

We can write:

<template>
  <div id="app">
    <b-form-input :state="valid" v-model="name" placeholder="name"></b-form-input>
  </div>
</template>

<script>
export default {
  computed: {
    valid() {
      return this.name.length > 0;
    }
  },
  data() {
    return {
      name: ""
    };
  }
};
</script>

to display a red border when the input value is empty.

Otherwise, we display a green border. The state prop is the validation state.

Formatter

We can add a formatted function to format the input value the way we want.

For instance, we can write:

<template>
  <div id="app">
    <b-form-input :formatter="formatter" v-model="value" placeholder="enter some text"></b-form-input>
    <p>{{value}}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      value: ""
    };
  },
  methods: {
    formatter(value) {
      return value.toLowerCase();
    }
  }
};
</script>

We added the formatter prop set to the formatter function. Inside it, we return the value state converted to lower case.

Then when we enter upper case text, it’ll be converted to lower case.

Read-Only Input

We can make the input read-only with the readonly prop.

Disabling Mouse Wheel Events on Numeric-Like Inputs

The no-wheel prop can be set to true to disable mouse wheel events on these inputs.

Datalist

We can add an autocomplete list with the datalist element.

For instance, we can write:

<template>
  <div id="app">
    <b-form-input list="fruits" name="fruit"></b-form-input>
    <datalist id="fruits">
      <option>apple</option>
      <option>orange</option>
      <option>grape</option>
    </datalist>
  </div>
</template>

<script>
export default {};
</script>

The list attribute of the b-form-input component and the id has to be the same.

Debounce

We can add a debounce prop to delay the registering of the input value.

So we can add:

<b-form-input v-model="value" type="text" debounce="500"></b-form-input>

Conclusion

We can add many kinds of text inputs with the b-form-input component.

The value can be formatted and delayed.