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.

Categories
BootstrapVue

BootstrapVue — Spin Button Customization

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 a spin button.

What’s a Spin Button?

A spin button is a numerical range form control.

We can include it with the b-form-spinbutton component.

For example, we can write:

<b-form-spinbutton v-model="value" min="1" max="100"></b-form-spinbutton>

We set the minimum and maximum allowed values with the min and max props.

v-model binds the inputted value to value .

Then we see a form control with a minus button on the left and a plus button on the right.

The number entered will be shown in the middle.

Make it Disabled

We can make the spin button disabled, which means that it’s non-interactive.

For instance. we can write:

<template>  
  <div id="app">  
    <b-form-spinbutton disabled v-model="value" min="1" max="100"></b-form-spinbutton>  
    <p>Value: {{ value }}</p>  
  </div>  
</template>  
<script>  
export default {  
  name: "App",  
  data() {  
    return {  
      value: 0  
    };  
  }  
};  
</script>

We added the disabled prop to make it non-interactive.

Read Only

We can set it to read-only as well.

This means that we can focus on it, but we can’t select a value.

For instance, we can do this with the readonly prop:

<template>  
  <div id="app">  
    <b-form-spinbutton readonly v-model="value" min="1" max="100"></b-form-spinbutton>  
    <p>Value: {{ value }}</p>  
  </div>  
</template>  
<script>  
export default {  
  name: "App",  
  data() {  
    return {  
      value: 0  
    };  
  }  
};  
</script>

Validation States

We can display the validation state.

To do this, we set the state prop.

For instance, we can write:

<template>  
  <div id="app">  
    <b-form-spinbutton :state='isValid' v-model="value" min="1" max="10"></b-form-spinbutton>  
    <p>Value: {{ value }}</p>  
  </div>  
</template>  
<script>  
export default {  
  name: "App",  
  data() {  
    return {  
      value: 0  
    };  
  },  
  computed: {  
    isValid(){  
      return !!this.value;  
    }  
  }  
};  
</script>

We set the state prop to the computed isValid property.

Then everything is green when we set a number.

Otherwise, everything is red.

Events

The b-form-spinbutton component emits a few events.

It emits the change event when the user released the mouse button when pressing the increment or decrement buttons.

For instance, we can write:

<template>  
  <div id="app">  
    <b-form-spinbutton wrap @change="value2 = $event" v-model="value" min="1" max="10"></b-form-spinbutton>  
    <p>Value 1: {{ value }}</p>  
    <p>Value 2: {{ value2 }}</p>  
  </div>  
</template>  
<script>  
export default {  
  name: "App",  
  data() {  
    return {  
      value: 0,  
      value2: 0  
    };  
  }  
};  
</script>

The $event variable has the value of the selected number.

We assigned that to value2 so we can display it in the bottom p element.

Conclusion

We can listen to events emitted by b-form-spinbutton and do something with the emitted value.

Also, we can make the form control disabled or read-only.

Read-only means we can focus but can’t do anything.

Disabled means that it’s not interactive at all.

We can also display the validation state of the control with the state prop.

Categories
BootstrapVue

BootstrapVue — Lazy Load Images and Input Groups

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 images that only load when we see them. We also look at how to add input groups.

Lazy Loaded Images

Lazy loading images is more efficient since we don’t have to load all the images upfront.

To do that, we can use the b-image-lazy component.

For instance, we can write:

<template>
  <div id="app">
    <b-img-lazy src="http://placekitten.com/200/200" alt="kitten"></b-img-lazy>
  </div>
</template>

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

Now our app will only load the image when it’s shown on the screen.

Input Groups

We can create input groups, which lets us group inputs with other components together.

To add an input group, we use the b-input-group component.

For instance, we can write:

<template>
  <div id="app">
    <b-input-group size="lg" prepend="$" append=".00">
      <b-form-input></b-form-input>
    </b-input-group>
  </div>
</template>

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

We change the size of the group to be large with size="lg" .

prepend lets us add something to the left the input.

append lets us add something to the right of the input.

So we should see the dollar sign on the left and .00 on the right. To customize the input group more, we can put code into slots.

For example, we can write:

<template>
  <div id="app">
    <b-input-group>
      <template v-slot:append>
        <b-input-group-text>
          <strong class="text-success">!</strong>
        </b-input-group-text>
      </template>
      <b-form-input></b-form-input>
    </b-input-group>
  </div>
</template>

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

Then we can add an exclamation mark with that’s green on the right.

Sub-Components

We can add subcomponents into the b-input-group-prepend and b-input-group-append components to add anything we want to the right.

For example, we can write:

<template>
  <div id="app">
    <b-input-group>
      <b-input-group-prepend>
        <b-button variant="primary">left button</b-button>
      </b-input-group-prepend>

      <b-form-input type="text"></b-form-input>

      <b-input-group-append>
        <b-button variant="outline-secondary">right button</b-button>
      </b-input-group-append>
    </b-input-group>
  </div>
</template>

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

We have the b-input-group-prepend and b-input-group-append components inside the b-input-group component.

This lets us add things that we can’t add with the prepend and append props.

In the example above, we added buttons inside each component.

Support Form Control Inside Input Groups

We can add the following components inside the b-input-group component:

  • <b-form-input>
  • <b-form-textarea>
  • <b-form-select>
  • <b-form-file>
  • <b-form-rating>
  • <b-form-tags>
  • <b-form-spinbutton>
  • <b-form-datepicker>
  • <b-form-timepicker>

Check and Radio Buttons

We can add checkboxes and radio buttons inside the b-input-group-prepend and b-input-group-append components.

For example, we can write:

<template>
  <div id="app">
    <b-input-group>
      <b-input-group-prepend is-text>
        <input type="checkbox">
      </b-input-group-prepend>
      <b-form-input></b-form-input>
    </b-input-group>
  </div>
</template>

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

We nest a checkbox inside the b-input-geoup-prepend component.

is-text applies the proper content for textual content.

We can also write the following to add a radio button the same way:

<template>
  <div id="app">
    <b-input-group>
      <b-input-group-prepend is-text>
        <input type="radio">
      </b-input-group-prepend>
      <b-form-input></b-form-input>
    </b-input-group>
  </div>
</template>

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

Custom Radio Button, Checkbox or Switch

The examples above added native radio buttons and checkboxes.

We can also add Bootstrap style radio button, checkbox or switch components.

For example, we can write:

<template>
  <div id="app">
    <b-input-group>
      <b-input-group-prepend is-text>
        <b-form-checkbox></b-form-checkbox>
      </b-input-group-prepend>
      <b-form-input></b-form-input>
    </b-input-group>
  </div>
</template>

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

to add a b-form-checkbox inside the b-input-group-prepend component.

Other components can be added the same way.

Conclusion

We can add lazy loading images with the b-img-lazy component.

Also, we can add input groups to add components on the left and right of input boxes.

Categories
BootstrapVue

BootstrapVue — Form Group

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 group inputs with form groups.

Form Group

Form groups let us add some structure to forms.

The b-form-group is a form group.

We can control the placing of legends and labels and place validation feedback text.

For instance, we can use it by writing:

<template>
  <div id="app">
    <b-form-group
      description="Your name."
      label="Your name"
      label-for="input-1"
      :invalid-feedback="invalidFeedback"
      :valid-feedback="validFeedback"
      :state="state"
    >
      <b-form-input trim id="input-1" v-model="name" :state="state"></b-form-input>
    </b-form-group>
  </div>
</template>

<script>
export default {
  computed: {
    state() {
      return this.name.length > 0;
    },
    invalidFeedback() {
      if (this.name.length > 0) {
        return "";
      } else {
        return "Please enter a name";
      }
    },
    validFeedback() {
      return this.state ? "Looks good" : "";
    }
  },
  data() {
    return {
      name: ""
    };
  }
};
</script>

We use the b-form-group component.

It has the feedback for form validation.

And it also includes the form input label.

The description prop lets us set the descriptions text displayed below the form input.

label has the labvel for the form input.

invalid-feedback is set to a function that returns the feedback text when the input value is invalid.

valid-feedback is set to a function that returns the feedback text when the input value is valid.

state is set to the validation state.

Then when we enter something valid, like text with 1 or more characters, it shows the valid text in green.

Otherwise, it shows the invalid value text in red.

The input box also has the corresponding change in color because we set the state prop for that.

Horizontal Layout

We can add the label-cols-sm and label-cols-klg props to change the column width of the labels.

This way, they can be less than the full width of the viewport.

For instance, we can write:

<template>
  <div id="app">
    <b-form-group
      description="Enter your name."
      label="Enter your name"
      label-for="input-horizontal"
      label-cols-sm="4"
      label-cols-lg="3"
    >
      <b-form-input id="input-horizontal"></b-form-input>
    </b-form-group>
  </div>
</template>

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

label-cols-sm is the column size for the label when the screen is narrow.

lable-cols-lg is the size for when the screen is wide.

Label Size

The label size can also change.

It can be changed with the label-size prop.

The value can be 'sm' or 'lg' .

For instance, we can write:

<template>
  <div id="app">
    <b-form-group description="Enter your name." label="Enter your name" label-size="sm">
      <b-form-input id="input-horizontal"></b-form-input>
    </b-form-group>
  </div>
</template>

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

The code is smaller than the default size with the label-size=”sm” .

Label Text Alignment

We can align the labels in various positions with the label-align prop.

It applies to breakpoints xs and up.

The value can be left , center , or right .

label-align-sm applies to breakpoint sm and up.

label-align-md applies to breakpoint md and up.

label-align-lg applies to breakpoint lg and up.

label-align-xl applies to breakpoint xl and up.

Nested Form Groups

Form groups can be nested.

For example, we can write:

<template>
  <div id="app">
    <b-form-group label-cols-lg="3" label="Person" label-size="lg" class="mb-0">
      <b-form-group
        label-cols-sm="3"
        label="Name:"
        label-align-sm="right"
        label-for="nested-name"
      >
        <b-form-input id="nested-name"></b-form-input>
      </b-form-group>
    </b-form-group>
  </div>
</template>

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

We need the b-form-group component.

The label is set for the outer group.

Also, we have the label on the inner form group.

Conclusion

We can create form groups with labels and form validation state rendered by this component.

The sizes of the form elements can be changed.

Also, we can nest form groups.