godbasin / vue-select2

select2 component in vue.
MIT License
123 stars 62 forks source link

Update proposal #67

Open r-peyron opened 2 years ago

r-peyron commented 2 years ago

Hello there ! Here is just a proposal for the main component with setup script (typescript).

<template>
  <select
      :id="props.id"
      ref="el"
      :disabled="props.disabled"
      :name="props.name"
      :required="props.required"
      class="form-control"/>
</template>

<script lang="ts" setup>
import $                                                  from 'jquery'
import { onBeforeUnmount, onMounted, ref, toRefs, watch } from 'vue'

import 'select2/dist/js/select2.full'
import 'select2/dist/css/select2.min.css'

type Props = {
  modelValue: any
  id?: string
  name?: string
  placeholder?: string
  options?: Array<any>
  disabled?: boolean
  required?: boolean
  settings?: object
}

type Emits = {
  (e: 'update:modelValue', data: any): void
  (e: 'select', data: any): void
}

const props = withDefaults(defineProps<Props>(), {
  id         : '',
  name       : '',
  placeholder: '',
  options    : () => [],
  disabled   : false,
  required   : false,
  settings   : () => ({})
})

const emit                    = defineEmits<Emits>()
const { modelValue, options } = toRefs(props)
const select2                 = ref()
const el                      = ref<HTMLSelectElement>()
const instance                = () => select2.value

const setOption = (val: Array<any> = []) => {
  select2.value.empty()
  select2.value.select2({
    placeholder: props.placeholder,
    ...props.settings,
    data: val
  })
  setValue(modelValue)
}

const setValue = val => {
  if (val instanceof Array) {
    select2.value.val([...val])
  } else {
    select2.value.val([val])
  }

  select2.value.trigger('change')
}

onMounted(() => {
  if (el.value) {
    select2.value = $(el.value)
        .select2({
          placeholder: props.placeholder,
          ...props.settings,
          data: props.options
        })
        .on('select2:select select2:unselect', ev => {
          emit('update:modelValue', select2.value.val())
          emit('select', ev['params']['data'])
        })

    setValue(modelValue.value)
  }
})

onBeforeUnmount(() => {
  select2.value.select2('destroy')
})

watch(options, (val) => {
  setOption(val)
})

watch(modelValue, (val) => {
  if (val instanceof Array) {
    select2.value.val([...val])
  } else {
    select2.value.val([val])
  }

  select2.value.trigger('change')
})

defineExpose({ instance })
</script>