Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(validation): Add 'optional' prop #15191

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 22 additions & 13 deletions packages/vuetify/src/composables/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface ValidationProps {
maxErrors: string | number
name: string | undefined
label: string | undefined
optional: boolean
readonly: boolean
rules: ValidationRule[]
modelValue: any
Expand All @@ -48,6 +49,7 @@ export const makeValidationProps = propsFactory({
},
name: String,
label: String,
optional: Boolean,
readonly: Boolean,
rules: {
type: Array as PropType<ValidationRule[]>,
Expand Down Expand Up @@ -81,7 +83,12 @@ export function useValidation (
? wrapInArray(props.errorMessages).slice(0, Math.max(0, +props.maxErrors))
: internalErrorMessages.value
})
const isEmpty = computed(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for this computed I think. should be fine to just use if (model.value)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it like that because originally I was also checking for an empty array, but I removed it I don't remember why. I could add it again.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I'm not sure whether if(model.value) is good, because we would count 0 as an empty value which I don't think it should be.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated isEmpty

Copy link
Member

@nekosaur nekosaur Apr 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the model value is always a string though, so 0 shouldn't be an issue

edit: hm, or how do we handle selects and stuff

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah there isn't really a consistent definition for "empty". Text fields would be '' or null, but both are valid select and radio values. [] could be empty for multi select but not single select or radio. Really the only empty value everywhere is undefined

Playground

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is your proposal then? Can we make it component-specific? Each component that uses validation could have a list of 'empty values'.

return model.value === undefined || model.value === '' || model.value === null ||
(Array.isArray(model.value) && model.value.length === 0)
})
const isValid = computed(() => {
if (props.optional && isEmpty.value) return true
if (props.error || errorMessages.value.length) return false
if (!props.rules.length) return true

Expand Down Expand Up @@ -156,24 +163,26 @@ export function useValidation (

isValidating.value = true

for (const rule of props.rules) {
if (results.length >= +(props.maxErrors ?? 1)) {
break
}
if (!props.optional || !isEmpty.value) {
for (const rule of props.rules) {
if (results.length >= +(props.maxErrors ?? 1)) {
break
}

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

if (result === true) continue
if (result === true) continue

if (typeof result !== 'string') {
// eslint-disable-next-line no-console
console.warn(`${result} is not a valid value. Rule functions must return boolean true or a string.`)
if (typeof result !== 'string') {
// eslint-disable-next-line no-console
console.warn(`${result} is not a valid value. Rule functions must return boolean true or a string.`)

continue
}
continue
}

results.push(result)
results.push(result)
}
}

internalErrorMessages.value = results
Expand Down