Skip to content

Commit

Permalink
feat: Added validation for Select
Browse files Browse the repository at this point in the history
  • Loading branch information
victoriakaropva committed Dec 5, 2023
1 parent 413f8d7 commit cde8c14
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 6 deletions.
34 changes: 33 additions & 1 deletion src/components/BuiSelect/BuiSelect.story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import BuiSelect from './BuiSelect.vue'
import BuiInput from '../BuiInput/BuiInput.vue'
import { ref } from 'vue'
const model = ref(null)
const model = ref('')
const options = [
{
name: 'One',
Expand Down Expand Up @@ -34,5 +34,37 @@ const options = [
<BuiInput label="Default" :required="true" />
</div>
</Variant>
<Variant title="With error status forced">
<div class="p-2">
<BuiSelect
label="Default"
:options="options"
:validation-status="'error'"
:has-forced-validation="true"
>
<template #validationMessage> Some error message </template>
</BuiSelect>
</div>
</Variant>
<Variant title="With success status forced">
<BuiSelect
label="Default"
:options="options"
:validation-status="'success'"
:has-forced-validation="true"
>
<template #validationMessage> Some success message </template>
</BuiSelect>
</Variant>
<Variant title="Required with dynamic validation">
<BuiSelect
label="Select right option (2)"
:options="options"
v-model="model"
:validation-status="model !== '1' ? null : 'error'"
>
<template #validationMessage v-if="model == '1'"> Do not select 'One'</template>
</BuiSelect>
</Variant>
</Story>
</template>
44 changes: 39 additions & 5 deletions src/components/BuiSelect/BuiSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,41 @@
</svg>
</span>
</span>
<div v-if="$slots.validationMessage" :class="validationWrapperClasses">
<slot name="validationMessage" />
</div>
</label>
</template>

<script lang="ts" setup>
import { computed } from 'vue'
import { computed, ref, watch } from 'vue'
import { twMerge } from 'tailwind-merge'
import RequiredIcon from '@/components/CommonElements/RequiredIcon.vue'
type ValidationStatus = 'success' | 'error'
type OptionsType = {
name: string
value: any
value: unknown
}
interface InputProps {
value?: string
value?: unknown
label?: string
options?: OptionsType[]
placeholder?: string
disabled?: boolean
required?: boolean
hasForcedValidation?: boolean
validationStatus?: ValidationStatus | null
}
const props = withDefaults(defineProps<InputProps>(), {
value: '',

Check failure on line 53 in src/components/BuiSelect/BuiSelect.vue

View workflow job for this annotation

GitHub Actions / build-pkg (18.x)

Type 'string' is not assignable to type '(props: Readonly<InputProps>) => unknown'.
label: '',
options: () => [],
placeholder: 'Please select one',
disabled: false,
required: false
required: false,
hasForcedValidation: false,
validationStatus: null
})
const emit = defineEmits(['input'])
Expand All @@ -62,6 +70,13 @@ const model = computed({
}
})
const isDirty = ref(false)
watch(model, (newValue, oldValue) => {
if (newValue !== oldValue && !isDirty.value) {
isDirty.value = true
}
})
const defaultLabelClasses =
'flex flex-row gap-2 mb-1 text-sm font-semibold leading-6 text-gray-900 dark:text-white'
const defaultSelectClasses =
Expand All @@ -75,9 +90,28 @@ const selectIconClasses = computed(() =>
)
)
const selectClasses = computed(() => {
return twMerge(defaultSelectClasses, props.disabled && disabledSelectClasses)
return twMerge(
defaultSelectClasses,
props.validationStatus === 'success' &&
'border-green-300 focus:border-green-300 focus:ring-green-200',
props.validationStatus === 'error' &&
(!!props.hasForcedValidation || isDirty.value) &&
'border-red-300 focus:border-red-300 focus:ring-red-200',
props.disabled && disabledSelectClasses
)
})
const validationWrapperClasses = computed(() =>
twMerge(
'text-sm font-normal mt-1',
props.validationStatus === 'success' ? 'text-green-300' : '',
props.validationStatus === 'error' && (!!props.hasForcedValidation || isDirty.value)
? 'text-red-300'
: '',
!props.hasForcedValidation && !isDirty.value && 'hidden'
)
)
const labelClasses = computed(() => {
return defaultLabelClasses
})
Expand Down

0 comments on commit cde8c14

Please sign in to comment.