Skip to content

Commit

Permalink
fix: validate selected items instead of search (#15304)
Browse files Browse the repository at this point in the history
fixes #15142
  • Loading branch information
KaelWD committed Jun 16, 2022
1 parent 6dfcf51 commit 4eec1d9
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 17 deletions.
Expand Up @@ -104,7 +104,7 @@ export const VAutocomplete = genericComponent<new <
v => transformIn(wrapInArray(v)),
v => {
const transformed = transformOut(v)
return props.multiple ? transformed : transformed[0]
return props.multiple ? transformed : (transformed[0] ?? null)
}
)
const { filteredItems } = useFilter(props, items, computed(() => isPristine.value ? undefined : search.value))
Expand Down Expand Up @@ -206,6 +206,8 @@ export const VAutocomplete = genericComponent<new <
<VTextField
ref={ vTextFieldRef }
modelValue={ search.value }
onUpdate:modelValue={ v => { if (v == null) model.value = [] } }
validationValue={ props.modelValue }
onInput={ onInput }
class={[
'v-autocomplete',
Expand All @@ -216,7 +218,6 @@ export const VAutocomplete = genericComponent<new <
},
]}
appendInnerIcon={ props.menuIcon }
dirty={ selected.value.length > 0 }
onClick:clear={ onClear }
onClick:control={ onClickControl }
onClick:input={ onClickControl }
Expand Down
15 changes: 6 additions & 9 deletions packages/vuetify/src/components/VCombobox/VCombobox.tsx
Expand Up @@ -108,17 +108,17 @@ export const VCombobox = genericComponent<new <
v => transformIn(wrapInArray(v || [])),
v => {
const transformed = transformOut(v)
return props.multiple ? transformed : transformed[0]
return props.multiple ? transformed : (transformed[0] ?? null)
}
)
const _search = ref('')
const search = computed<string>({
get: () => {
if (props.multiple) return _search.value

const item = items.value.find(({ props }) => props.value === model.value[0])
const item = items.value.find(item => item.value === model.value[0]?.value)

return item?.props.value
return item?.value
},
set: val => {
if (props.multiple) {
Expand Down Expand Up @@ -237,9 +237,6 @@ export const VCombobox = genericComponent<new <
search.value = ''
}
}
function onInput (e: InputEvent) {
search.value = (e.target as HTMLInputElement).value
}
function onAfterLeave () {
if (isFocused.value) isPristine.value = true
}
Expand Down Expand Up @@ -290,8 +287,9 @@ export const VCombobox = genericComponent<new <
return (
<VTextField
ref={ vTextFieldRef }
modelValue={ search.value }
onInput={ onInput }
v-model={ search.value }
onUpdate:modelValue={ v => { if (v == null) model.value = [] } }
validationValue={ props.modelValue }
class={[
'v-combobox',
{
Expand All @@ -302,7 +300,6 @@ export const VCombobox = genericComponent<new <
},
]}
appendInnerIcon={ props.items.length ? props.menuIcon : undefined }
dirty={ selected.value.length > 0 }
onClick:clear={ onClear }
onClick:control={ onClickControl }
onClick:input={ onClickControl }
Expand Down
6 changes: 4 additions & 2 deletions packages/vuetify/src/components/VSelect/VSelect.tsx
Expand Up @@ -108,7 +108,7 @@ export const VSelect = genericComponent<new <
v => transformIn(wrapInArray(v)),
v => {
const transformed = transformOut(v)
return props.multiple ? transformed : transformed[0]
return props.multiple ? transformed : (transformed[0] ?? null)
}
)
const selections = computed(() => {
Expand Down Expand Up @@ -162,6 +162,9 @@ export const VSelect = genericComponent<new <
return (
<VTextField
ref={ vTextFieldRef }
modelValue={ model.value.map(v => v.props.value).join(', ') }
onUpdate:modelValue={ v => { if (v == null) model.value = [] } }
validationValue={ props.modelValue }
class={[
'v-select',
{
Expand All @@ -176,7 +179,6 @@ export const VSelect = genericComponent<new <
onClick:input={ onClickControl }
onClick:control={ onClickControl }
onBlur={ () => menu.value = false }
modelValue={ model.value.map(v => v.props.value).join(', ') }
onKeydown={ onKeydown }
>
{{
Expand Down
14 changes: 10 additions & 4 deletions packages/vuetify/src/composables/validation.ts
Expand Up @@ -27,6 +27,7 @@ export interface ValidationProps {
rules: ValidationRule[]
modelValue: any
'onUpdate:modelValue': ((val: any) => void) | undefined
validationValue: any
}

export const makeValidationProps = propsFactory({
Expand All @@ -47,6 +48,7 @@ export const makeValidationProps = propsFactory({
default: () => ([]),
},
modelValue: null,
validationValue: null,
})

export function useValidation (
Expand All @@ -55,10 +57,14 @@ export function useValidation (
id: MaybeRef<string | number> = getUid(),
) {
const model = useProxiedModel(props, 'modelValue')
const validationModel = computed(() => props.validationValue ?? model.value)
const form = useForm()
const internalErrorMessages = ref<string[]>([])
const isPristine = ref(true)
const isDirty = computed(() => wrapInArray(model.value === '' ? null : model.value).length > 0)
const isDirty = computed(() => !!(
wrapInArray(model.value === '' ? null : model.value).length ||
wrapInArray(validationModel.value === '' ? null : validationModel.value).length
))
const isDisabled = computed(() => !!(props.disabled || form?.isDisabled.value))
const isReadonly = computed(() => !!(props.readonly || form?.isReadonly.value))
const errorMessages = computed(() => {
Expand Down Expand Up @@ -92,8 +98,8 @@ export function useValidation (
form?.unregister(uid.value)
})

watch(model, () => {
if (model.value != null) validate()
watch(validationModel, () => {
if (validationModel.value != null) validate()
})

function reset () {
Expand All @@ -117,7 +123,7 @@ export function useValidation (
}

const handler = typeof rule === 'function' ? rule : () => rule
const result = await handler(model.value)
const result = await handler(validationModel.value)

if (result === true) continue

Expand Down

0 comments on commit 4eec1d9

Please sign in to comment.