Part 3 (b): How to Build a Self-Contained Component

Part 3 (b): How to Build a Self-Contained Component

·

4 min read

How to build a custom dropdown select

Using a custom select built from scratch instead of the default select-option element in HTML gives a lot of flexibility to you as a developer; you can modify and manipulate a lot of things yourself while also giving it a favorable aesthetic design that suits your business needs or functionality.

Step 1: Create a new component file. Inside your project directory, navigate to the src/components/common folder (or create it if it doesn't exist). Create a new file for your custom select component, e.g., CustomSelect.vue.

Step 2: Define the custom select component. Open the CustomSelect.vue file and define your custom select component using Vue's Single File Component syntax. Here's an example code for a custom select component:

src/components/common/CustomSelect.vue

<template>
   <div class="form-control">
      <label v-show="isLabel" :for="IdName">{{ labelValue }}</label>
      <div class="input-wrapper">
         <input 
            type="text"
            :id="IdName"
            :placeholder="PlaceHolder"
            @focus="openDropDown"
            :value="isSelected"
            readonly
         >
         <span :class="[ showDropDown ? 'open' : '']" @click="showDropDown = !showDropDown">></span>
      </div>
      <div v-if="showDropDown" class="drop-down">
         <p v-for="(data , index) in options" :key="index" @click="isSelect(data)">{{ data }}</p>
      </div>
   </div>
</template>
<script>
export default {
   name:'CustomInput',
   props: {
      labelValue: {
         type: String,
         default: 'Label',
      },
      options: {
         type: Array,
         required: true,
      },
      isLabel: {
         type: Boolean,
         default: false,
      },
      PlaceHolder: {
         type: String,
         default:'Select',
      },
      IdName: {
         type: String,
         default: '',
      },
   },
   data(){
      return {
        showDropDown: false,
        textData: '',
        isSelected: '',
      }
   },
   methods: {
      isSelect(value){
        this.isSelected = value;
        this.$emit('data', this.isSelected)
        this.showDropDown = false;
      },
      openDropDown(){
         this.showDropDown = true;
      },
   }
}
</script>
<style lang="scss" scoped>
   .form-control {
      position: relative;

      & input {
         padding: 10px ;
         font-size: 16px;
         border: 2px solid #eee;
         border-radius: 5px;
         width: 100%;
         box-sizing: border-box;

         &:focus {
            border: 3px solid #67679ac5;
         }
      }

      .drop-down {
         box-shadow: 0px 2px 5px rgba(0, 0, 0, .3);
         position: absolute;
         background: #fff;
         width: 100%;
         z-index: 111;
         padding: 0;
         overflow: hidden;


         & p{
            list-style-type: none;
            flex-direction: column;
            width: 100%;
            padding: 7px 7px;
            font-size: 16px;
            margin: 0;
            text-align: left;


            &:hover{
              background: #eee;
              cursor: pointer;
            }
         }
      }
   }

   .input-wrapper{
      position: relative;
      span {
         position: absolute;
         right: 5px;
         top: 0;
         transition: .5s ease;
         transform: rotate(90deg);
         cursor: pointer;
         color: #7777f3;
         padding: 10px;
         font-weight: bold;

         &.open {
            transform: rotate(270deg);
         }
      }
   }
</style>

In this example, the CustomSelect component displays a selected option that is passed from its parent components and a dropdown menu with multiple options. Clicking on the selected option toggles the visibility of the dropdown menu. Selecting an option from the dropdown updates the selected option and also passes the selected value up to the parent component. Here are some of the props configured to pass from the parent to this component.

labelValue: The label title. You can pass it from the parent component to the child component accepting a string of data.

options: This accepts an array of data; it will display on the dropdown select, and the user will be allowed to select from the data.

isLabel: This accepts a boolean value; it is false by default and can be set to true if you need to use the internal label.

PlaceHolder: You can specify a placeholder name from the parent component, it's 'Select' by default.

IdName: You can also pass this to it as a prop for the ID name. Ideally used together when you need the component label

Step 3: Use the custom select component.

src/views/HomeView.vue

<template>
  <div class="home">
    <!-- render emit data -->
    <form class="form__container" action="">
      <CustomSelect :options="select" @data="handleSelected"/>
    </form>
  </div>
</template>

<script>

import CustomSelect from '@/components/common/CustomSelect.vue';

export default {
  name: 'HomeView',
  components: {
    CustomSelect,
  },
  data(){
    return {
      parentData: 'You are learning about props in this article',
      newMsg: 'hello',
      select: [
        'lagos',
        'Abuja',
        'London',
        'New York'
      ]
    }
  },
  methods: {
    handleSelected(value){
      console.log(value);
    }
  }
}
</script>

In this example, the CustomSelect component is imported and registered as a component within the Home View page. You can now use in the App template to render your custom select component.

Image description

In conclusion, building a custom select functionality with Vue.js involves creating a separate component that encapsulates the select behavior. By following the steps outlined above, you can create a self-contained component that displays a selected option and a dropdown menu with selectable options. The component allows you to toggle the visibility of the dropdown menu and update the selected option based on user interactions. This approach provides flexibility and reusability, allowing you to easily incorporate the custom select component into other parts of your Vue.js application.