The issue with useForm is that it becomes a bit hacky when we try to use validation in child components, where most the time using useValidation directly feels more natural, but then at the moment, we lose ability to get function like validateAndNotify since this is exposed by useForm.
Another is that by separating data and validation composable, it's much easier to have custom component that uses the data. For example,
To avoid breaking change, bit brutal but call this useD. It also avoid conflict on having it return data object. You know, it's nicer than having duplicate name like const { data } = useData(...).
The important feature of Data is that it can restore its initial state.
Same as useD, to avoid breaking change, introduce new useV composable. It should be a wrapper of Vuelidate Validation composable, with extra methods.
// Omitting types but it should inherid Vuelidate types.
interface V {
validation: ComputedRef<VuelidateValidation>
validate(): void
validateAndNotify(): void
reset(): void
}
interface Rules {
[key: string]: Rule
}
interface Rule {
[key: string]: Rules | RuleValidator
}
interface RuleValidator {
hasCustomMessage: boolean
validator: VuelidateValidationRule
}
function useV(
data: MaybeRefOrGetter<Record<string, any>>,
rules: Rules
): V
OK, so the important part is that we introduce new Rule object to achieve i18n.
At first, we will re-create all rules. We can re-use validators we have. But maybe place rules in rules-2 directory...? 😓
This new Rule object should return RuleValidator type.
In useV, iterate all provided rules, and then inject custom messages depending on current user locale.
Pseudo code would look something like this.
function useV(
data: MaybeRefOrGetter<Record<string, any>>,
rules: Rules
): V {
// Implement a way to get current locale messages.
// This should be something like:
// {
// v_required: 'This field is required',
// v_max_length: (length) => `This field must be less than ${length} characters`
// }
}
const messages = getCurrentLocaleMessageBag()
// Loop all rules and transform into Vuelidate rules by
// injecting localized messages.
const vuelidateRules = computed(() => {
// Loop rules. Say we got `required` rule.
const r = getRuleToProcess()
return vuelidateHelpers.withMessage(
() => messages[r.messageKey],
(value) => r.validator(value)
)
})
const validations = useVuelidateValidation(
vuelidateRules,
data
)
return {
validation
}
}
We can use message?: string option in RuleValdator to skip injecting default message.
I was thinking a lot about i18n support for Sefirot, and the hard part part is validation rule error messages.
While thinking about it, and also I had few thoughts on things that I didn't like about current
useForm
api, here is the new idea.Basic example
Deprecate
useForm
The issue with
useForm
is that it becomes a bit hacky when we try to use validation in child components, where most the time usinguseValidation
directly feels more natural, but then at the moment, we lose ability to get function likevalidateAndNotify
since this is exposed byuseForm
.Another is that by separating data and validation composable, it's much easier to have custom component that uses the data. For example,
useD
To avoid breaking change, bit brutal but call this
useD
. It also avoid conflict on having it returndata
object. You know, it's nicer than having duplicate name likeconst { data } = useData(...)
.The important feature of Data is that it can restore its initial state.
useV
Same as
useD
, to avoid breaking change, introduce newuseV
composable. It should be a wrapper of Vuelidate Validation composable, with extra methods.OK, so the important part is that we introduce new
Rule
object to achieve i18n.At first, we will re-create all rules. We can re-use validators we have. But maybe place rules in
rules-2
directory...? 😓This new Rule object should return
RuleValidator
type.In
useV
, iterate all provided rules, and then inject custom messages depending on current user locale.Pseudo code would look something like this.
We can use
message?: string
option inRuleValdator
to skip injecting default message.