Skip to content
Snippets Groups Projects
FormGroup.vue 1.39 KiB
Newer Older
  • Learn to ignore specific revisions
  • <template>
      <div class="form-group tw-block" :class="formGroupClass">
        <label :for="id" class="tw-text-gray-500 tw-font-medium tw-pt-1">{{ label }}</label>
        <div class="tw-flex tw-flex-col">
          <slot v-bind="controlAttributes" />
          <div v-if="hasErrors" :id="errorsId" class="invalid-feedback tw-order-first">
            <template v-for="(error, index) in errorList" :key="index">
              <p class="last:tw-mb-0">{{ t(`error.${error.code}`) }}</p>
            </template>
          </div>
        </div>
      </div>
    </template>
    
    <script lang="ts" setup>
    import { computed, inject } from 'vue'
    import { useId } from '@/util'
    import { useI18n } from '@/i18n'
    
    type Error = {
      code: string
    }
    
    const props = defineProps<{
      label: string
      customControl?: boolean
      errors?: undefined | Error[]
    }>()
    
    const { t } = useI18n()
    const formGroupClass = inject('formGroupClass', undefined)
    const id = useId('form-group-control')
    const errorsId = useId('form-group-errors')
    const errorList = computed<Error[]>(() => props.errors ?? [])
    const hasErrors = computed(() => errorList.value.length > 0)
    const controlAttributes = computed(() => ({
      class: [
        'tw-order-first',
        { 'is-invalid': hasErrors.value, 'form-control': !props.customControl },
      ],
      'aria-describedby': hasErrors.value ? errorsId.value : '',
      id: id.value,
    }))
    </script>
    
    <script lang="ts">
    export default {
      compatConfig: {
        MODE: 3,
      },
    }
    </script>