Categories
BootstrapVue

BootstrapVue — Customizing Form Tags

Spread the love

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.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *