Forms

Select

The Select component is a user interface element used for choosing one or multiple options from a predefined list. It enhances form usability by providing an intuitive selection method.

If you are using it with vue, you should import choices.js by npm install choices.js

Code structure

The following is the basic structure of a Select component:

                    
HTML
<select class="js-choices" aria-label="" dir="rtl" data-placeholder="اختر الدولة من القائمة"> <option value="1">المملكة العربية السعودية</option> <option value="2">السودان</option> <option value="3">مصر</option> <option value="4">الجزائر</option> </select>

Single Select

Allows users to choose one option from a dropdown.

View Mode
                          
HTML
<label class="form-label">الدولة</label> <select class="js-choices" aria-label="" dir="rtl" data-placeholder="اختر الدولة من القائمة"> <option value="1">المملكة العربية السعودية</option> <option value="2">السودان</option> <option value="3">مصر</option> <option value="4">الجزائر</option> </select>
<!-- Usage Example -->
<SingleSelect
  id="country-select"
  label="الدولة"
  placeholder="اختر الدولة من القائمة"
  v-model="selectedCountry"
  :required="true"
  :searchable="false"
  :options="[
    { value: '1', label: 'المملكة العربية السعودية' },
    { value: '2', label: 'السودان' },
    { value: '3', label: 'مصر' },
    { value: '4', label: 'الجزائر' },
  ]"
/>
<!-- Vue Component Code Block -->
<template>
  <div>
    <label class="form-label">{{ label }}</label>
    <select
      class="js-choices"
      :id="id"
      aria-label=""
      dir="rtl"
      :data-placeholder="placeholder"
      v-model="selectedValue"
      :required="required"
      :name="name"
    >
    </select>
  </div>
</template>

<script setup>
import { onMounted, ref, watch, nextTick } from 'vue'
import Choices from 'choices.js'

const props = defineProps({
  id: String,
  label: String,
  required: Boolean,
  modelValue: String,
  options: Array,
  searchable: Boolean,
  placeholder: String,
  name: String,
})

const emit = defineEmits(['update:modelValue'])

const selectedValue = ref(props.modelValue)

watch(selectedValue, (newValue) => {
  emit('update:modelValue', newValue)
})

onMounted(() => {
  nextTick(() => {
    const selectElement = document.querySelector(`#${props.id}`)
    if (selectElement) {
      const choicesInstance = new Choices(selectElement, {
        searchEnabled: props.searchable,
        itemSelectText: props.placeholder,
        removeItemButton: false,
        shouldSort: false,
      })

      choicesInstance.setChoices(
        props.options.map((option) => ({
          value: option.value,
          label: option.label,
          selected: option.value === selectedValue.value,
        })),
        'value',
        'label',
        false,
      )

      selectElement.addEventListener('change', (e) => {
        selectedValue.value = e.detail.value
      })
    }
  })
})
</script>

Multi Select

The following is the basic structure of a Select component .select-multi

View Mode
                          
HTML
<label class="form-label">حدد الاجراءات</label> <select class="js-choices-no-search" aria-label="" dir="rtl" data-placeholder="حدد أكثر من إجراء..."> <option value="1">الاجراء الأول</option> <option value="2">الاجراء الثاني</option> <option value="3">الاجراء الثالث</option> <option value="4">الاجراء الرابع</option> <option value="5">الاجراء الخامس</option> </select>
<!-- Usage Example -->
<MultiSelect
  id="choices-select"
  label="حدد الاجراءات"
  placeholder="حدد أكثر من إجراء..."
  v-model="selectedChoices"
  :required="true"
  :searchable="false"
  :options="[
    { value: '1', label: 'الاجراء الأول' },
    { value: '2', label: 'الاجراء الثاني' },
    { value: '3', label: 'الاجراء الثالث' },
    { value: '4', label: 'الاجراء الرابع' },
    { value: '5', label: 'الاجراء الخامس' },
  ]"
/>
<!-- Vue Component Code Block -->
<template>
  <div>
    <label class="form-label">{{ label }}</label>
    <select
      multiple
      class="js-choices-no-search"
      :id="id"
      aria-label=""
      dir="rtl"
      :data-placeholder="placeholder"
      v-model="selectedValue"
      :required="required"
      :name="name"
    >
    </select>
  </div>
</template>

<script setup>
import { onMounted, ref, watch, nextTick } from 'vue'
import Choices from 'choices.js'

const props = defineProps({
  id: String,
  label: String,
  required: Boolean,
  modelValue: Array,
  options: Array,
  searchable: Boolean,
  placeholder: String,
  name: String,
})

const emit = defineEmits(['update:modelValue'])

const selectedValue = ref([...(props.modelValue || [])])

watch(selectedValue, (newValue) => {
  emit('update:modelValue', newValue)
})

onMounted(() => {
  nextTick(() => {
    const selectElement = document.querySelector(`#${props.id}`)
    if (selectElement) {
      const choicesInstance = new Choices(selectElement, {
        searchEnabled: props.searchable,
        itemSelectText: '',
        shouldSort: false,
        removeItemButton: true,
      })

      choicesInstance.setChoices(
        props.options.map((option) => ({
          value: option.value,
          label: option.label,
          selected: selectedValue.value.includes(option.value),
        })),
        'value',
        'label',
        false,
      )

      selectElement.addEventListener('change', () => {
        const selectedOptions = Array.from(selectElement.selectedOptions).map((opt) => opt.value)
        selectedValue.value = selectedOptions
      })
    }
  })
})
</script>
Last updated 3 months ago