paint-brush
Making a Custom Select Component in Vue.js [A How-To Guide]by@wagslane
10,712 reads
10,712 reads

Making a Custom Select Component in Vue.js [A How-To Guide]

by Lane WagnerFebruary 26th, 2020
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

Making a Custom Select component in Vue.js [A How-To Guide] is a guide to creating your own custom select components. In this article, you will learn how to build a Vue.js component that can be styled using completely custom CSS. The HTML is just an example of what we use for the Qvault app. Feel free to use the CSS to create your own select components to completely change the design of a select tag. For example, check out the live demo for a live example.

People Mentioned

Mention Thumbnail

Company Mentioned

Mention Thumbnail
featured image - Making a Custom Select Component in Vue.js [A How-To Guide]
Lane Wagner HackerNoon profile picture

Customizing the design of a select tag is notoriously difficult. Sometimes it's impossible without building your own from scratch using a combination of styled divs with custom JavaScript. In this article, you will learn how to build a Vue.js component that can be styled using completely custom CSS.

Demo:

The HTML

<template>
  <div
    class="custom-select"
    :tabindex="tabindex"
    @blur="open = false"
  >
    <div
      class="selected"
      :class="{open: open}"
      @click="open = !open"
    >
      {{ selected }}
    </div>
    <div
      class="items"
      :class="{selectHide: !open}"
    >
      <div
        class="item"
        v-for="(option, i) of options"
        :key="i"
        @click="selected=option; open=false; $emit('input', option)"
      >
        {{ option }}
      </div>
    </div>
  </div>
</template>

The following is important to note:

  • The tabindex property allows our component to be focused, which in turn allows it to be blurred. The blur event closes our component when a user clicks outside of the component.
  • By emitting the selected option using the 'input' parameter, the parent component can react to changes easily.

The JavaScript

<script>
export default {
  props:{
    options:{
      type: Array,
      required: true
    },
    tabindex:{
      type: Number,
      required: false,
      default: 0
    }
  },
  data() {
    return {
      selected: this.options.length > 0 ? this.options[0] : null,
      open: false
    };
  },
  mounted(){
    this.$emit('input', this.selected);
  }
};
</script>

Also, important things to note:

We also emit the selected value on mount so that the parent doesn't need to set the default value explicitly.If our select component is a small part of a larger form, then we want to be able to set the correct tabindex.

The CSS

<style scoped>

.custom-select {
  position: relative;
  width: 100%;
  text-align: left;
  outline: none;
  height: 47px;
  line-height: 47px;
}

.selected {
  background-color: #080D0E;
  border-radius: 6px;
  border: 1px solid #858586;
  color: #ffffff;
  padding-left: 8px;
  cursor: pointer;
  user-select: none;
}

.selected.open{
  border: 1px solid #CE9B2C;
  border-radius: 6px 6px 0px 0px;
}

.selected:after {
  position: absolute;
  content: "";
  top: 22px;
  right: 10px;
  width: 0;
  height: 0;
  border: 4px solid transparent;
  border-color: #fff transparent transparent transparent;
}

.items {
  color: #ffffff;
  border-radius: 0px 0px 6px 6px;
  overflow: hidden;
  border-right: 1px solid #CE9B2C;
  border-left: 1px solid #CE9B2C;
  border-bottom: 1px solid #CE9B2C;
  position: absolute;
  background-color: #080D0E;
  left: 0;
  right: 0;
}

.item{
  color: #ffffff;
  padding-left: 8px;
  cursor: pointer;
  user-select: none;
}

.item:hover{
  background-color: #B68A28;
}

.selectHide {
  display: none;
}
</style>

This CSS is just an example, its what we use for the Qvault app. Feel free to completely change the styling to whatever your needs are.

I hope this helps you create your own custom select components, the following is a link to a gist of the full component:

Again, check out the demo for a live example:

By Lane Wagner @wagslane

Download Qvault: https://qvault.io

Star our Github: https://github.com/q-vault/qvault

Read the original