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.

Categories
BootstrapVue

BootstrapVue — Time Picker Internationalization and Images

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 time picker and images.

Time Picker Internationalization

We can change the label values of the time picker to make it work with different locales.

For example, we can write:

<template>
  <div id="app">
    <b-form-timepicker v-model="value" v-bind="de" show-seconds :locale="locale"></b-form-timepicker>
    <div>Value: {{ value }}</div>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      value: "",
      de: {
        labelHours: "Stunden",
        labelMinutes: "Minuten",
        labelSeconds: "Sekunden",
        labelIncrement: "Erhöhen",
        labelDecrement: "Verringern",
        labelSelected: "Ausgewählte Zeit",
        labelNoTimeSelected: "Keine Zeit ausgewählt",
        labelCloseButton: "Schließen"
      }
    };
  }
};
</script>

We have the v-bind directive that binds the labels as props to the b-form-timerpicker component.

Now we’ll see Germany labels for the controls instead of the default English labels.

Hour Cycle

We can change how the hours are displayed by changing the hour cycle.

There are 4 ways to display the hours.

'h12' displays from 1 to 12.

'h23' displays from 0 to 23.

'h11' displays 0 to 11, and 'h24' displays 1 to 24.

These are all available as their own props.

To display hours in the 12-hour style, we set the hour12 prop to true.

To display 24 hours style, we set hour12 to false .

The formatted time string may be h12 or h23 depending on the value returned by Intl.DateTimeFormat .

For instance, we can write:

<template>
  <div id="app">
    <b-form-timepicker v-model="value" :hour12="true" :locale="locale"></b-form-timepicker>
    <div>Value: {{ value }}</div>
  </div>
</template>

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

and display hours from 1 to 12, but it can be formatted as 0 to 11 or 1 to 12 depending on the locale.

Images

We can add the b-img component to display responsive images.

There’s also the b-img-lazy to load images only when they’re shown on the screen.

For instance, we can write:

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

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

to add an image to the component.

fluid means that the image won’t grow with its container.

To make it grow with the container, we can use the fluid-grow prop.

For instance, we can write:

<template>
  <div id="app">
    <b-img src="http://placekitten.com/200/200" fluid-grow alt="cat"></b-img>
  </div>
</template>
<script>
export default {
  name: "App"
};
</script>

Thumbnails

To make the image with the thumbnail, we can use the thumbnail prop.

For example, we can write:

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

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

This will make the image display as a thumbnail.

Rounded Corners

We can make the image corners rounded by using the rounded prop.

For instance, we can write:

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

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

Now we have rounded corners on our image.

It can also have a set value set for it, including 'top' , 'right' , 'bottom' , 'left' , 'circle' , or a 0.

0 turns off rounding.

So we can write:

<template>
  <div id="app">
    <b-img src="http://placekitten.com/200/200" rounded="circle"></b-img>
  </div>
</template>

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

Then we can see the images rounded.

Aligning Images

We can align the images by adding the left, center and right props.

For instance, we can add the image by using those props as follows:

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

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

Then we align the image to the right side of the page.

Solid Color Images

We can make the image a solid color.

For instance, we can write:

<template>
  <div id="app">
    <b-img blank blank-color="green" alt="green image" width='200' height='200'></b-img>
  </div>
</template>

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

We have the blank prop to make the image blank.

blank-color sets the color.

alt is the descriptive text.

width is the width and height is the height of the image.

Conclusion

We can customize the locale of the time picker.

Also, we can add images with the b-img component.

They can have an image or be blank.

Categories
BootstrapVue

BootstrapVue — File Input

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 a file input with BootstrapVue.

File Upload

We can add a file upload widget by using the b-form-file component.

For example, we can write:

<template>
  <div id="app">
    <b-form-file
      v-model="file"
      :state="Boolean(file)"
      placeholder="choose file..."
      drop-placeholder="drop file..."
    ></b-form-file>
    <p>{{ file ? file.name : '' }}</p>
  </div>
</template>

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

The b-form-file component lets us add a file input.

v-model gets the selected file object and binds it to the file property.

state is for setting the validation state.

placeholder is a placeholder displayed for the regular file input.

drop-placeholder is the placeholder displayed when we’re dropping files.

Then we display the file name below it.

We can use the multiple prop to let users add multiple files.

Drop mode is enabled by default.

We can add the no-drop prop to disable dropping files.

Limiting File Types

We can limit the file types that can be uploaded.

To do that, we just have to set the accept prop.

For instance, we can write:

<b-form-file accept="image/jpeg, image/png, image/gif"></b-form-file>

or:

<b-form-file accept=".jpg, .png, .gif"></b-form-file>

We can set the mime type or the file extension of the file.

Sizing

The sizing of the file upload box can also be changed.

The size prop lets us change the size. 'sm' is for small and 'lg' is for large.

Otherwise, we get the default size.

For instance, we can write:

<template>
  <div id="app">
    <b-form-file v-model="file" :state="Boolean(file)" size="sm"></b-form-file>
    <p>{{ file ? file.name : '' }}</p>
  </div>
</template>

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

File Name Formatter

We can format the file name for the selected file the way we like.

To do that, we can create a function.

For instance, we can write:

<template>
  <div id="app">
    <b-form-file multiple :file-name-formatter="formatNames"></b-form-file>
    <p>{{ file ? file.name : '' }}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    formatNames(files) {
      if (files.length === 1) {
        return files[0].name;
      } else {
        return `${files.length} files chosen`;
      }
    }
  }
};
</script>

The files parameter is an array-like object with the chosen files.

Therefore, we can check the length property and return the string we want to display.

Formatting File Names with Scoped Slots

To display something other than text when files are chosen, we can add items to slots.

To do that, we write:

<template>
  <div id="app">
    <b-form-file multiple>
      <template slot="file-name" slot-scope="{ names }">
        <b-badge>chosen file: {{ names[0] }}</b-badge>
        <b-badge v-if="names.length > 1" variant="dark" class="ml-1">{{ names.length }} files chosen</b-badge>
      </template>
    </b-form-file>
  </div>
</template>

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

We populate the file-name slot with our own content.

The names array lets us access the file names.

Autofocus

We can add the autofocus prop to make the file input focus when it’s loaded or when it’s displayed inside a keep-alive component.

Clearing File Selection

We can clear file selection by setting the file object to null or undefined .

For instance, we can write:

<template>
  <div id="app">
    <b-form-file v-model="file"></b-form-file>
    <b-button @click="file = undefined">Reset file input</b-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      file: undefined
    };
  }
};
</script>

We just set file to undefined to clear the input.

Also, we can clear it by setting a ref for the file input and then call reset on it.

We can write:

<template>
  <div id="app">
    <b-form-file v-model="file" ref="file-input" class="mb-2"></b-form-file>
    <b-button @click="clearFiles">Reset file input</b-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      file: undefined
    };
  },
  methods: {
    clearFiles() {
      this.$refs["file-input"].reset();
    }
  }
};
</script>

This does the same thing as resetting by clearing the model.

Conclusion

BootstrapVue comes with a file input component.

We can do all the things we can think of with it, like dropping files, selecting files, and clearing file selection.