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.