Validation System
Validation is mainly carried by fields, while Form provides aggregate entry points. A field declares rules, validates itself, and stores feedback. form.validate() / form.submit() aggregate data fields from the field tree and dispatch validation in batch.
Most validation capabilities depend on @silver-formily/validator. You can also refer to the validator's Quick Start guide.
Validators
Fields use validator to describe validation rules.
String Format
A string is treated as format, which is a shorthand for format validation:
field.validator = 'email' // same as { format: 'email' }
field.validator = 'url'Custom formats can be registered through registerValidateFormats.
Function Validator
A function can return a string, boolean, or feedback-like object:
field.validator = (value) => {
return value ? '' : 'Required'
}
field.validator = {
validator: value => value.length > 3,
message: 'At least 3 characters',
}
field.validator = (value) => {
return {
type: 'warning',
message: value?.endsWith('@company.com') ? '' : 'Company email is recommended',
}
}Object Rule
Object rules can express richer constraints:
field.validator = {
required: true,
format: 'email',
minLength: 3,
maxLength: 20,
message: 'Invalid format',
}Custom rules can be registered through registerValidateRules.
Rule Array
Arrays combine multiple rules. Different forms are normalized into a rule array:
field.validator = [
'email',
{ required: true },
value => value ? '' : 'Required',
]
field.validator = [
{ format: 'email' },
{ required: true },
{ validator: value => value ? '' : 'Required' },
]Trigger Timing
Each rule object can use triggerType to control when it is triggered:
| triggerType | Timing |
|---|---|
onInput | On input, default |
onBlur | On blur |
onFocus | On focus |
field.validator = [
{ required: true },
{ format: 'email', triggerType: 'onBlur' },
]These field methods trigger matching rules:
field.onInput('silver')
field.onFocus()
field.onBlur()Manual validation can target a trigger type. Without an argument, all rules are validated:
await field.validate()
await field.validate('onBlur')Validation Strategy
validateFirst controls whether validation stops after the first failed rule.
form.createField({
name: 'username',
validateFirst: true,
validator: [
{ required: true },
{ minLength: 3 },
],
})The default is false, so failed rules do not prevent later rules from running, and the field can return complete feedback.
Validation State
Fields use validated to distinguish “currently has no errors” from “has actually passed validation”:
field.valid
field.validated
field.validateStatusvalid starts as true and only means that the field currently has no errors. validated becomes true only after at least one rule matching the current trigger type has completed. It returns to false when the value changes, a new matching validation starts, or the field is reset.
After normal validation succeeds, validateStatus is success. Failed, warning, and in-progress validations report error, warning, and validating. Fields without rules, or without rules matching the current trigger, keep validateStatus as undefined.
Normal success does not write success feedback, so selfSuccesses and form.successes remain empty. A validator must explicitly return { type: 'success', message } when a success message is required.
Feedback
Validation results are stored in field.feedbacks. A field stores IFieldFeedback, which does not include path information:
interface IFieldFeedback {
triggerType?: 'onInput' | 'onFocus' | 'onBlur'
type?: 'error' | 'success' | 'warning'
code?: 'ValidateError' | 'ValidateSuccess' | 'ValidateWarning'
| 'EffectError' | 'EffectSuccess' | 'EffectWarning'
messages?: any[]
}When Form or a parent field aggregates feedback, it adds optional path and address properties to produce IFormFeedback.
Fields provide type-based feedback helpers:
field.feedbacks
field.errors
field.warnings
field.successes
field.selfErrors
field.selfWarnings
field.selfSuccessesself-prefixed properties only read feedback from the current field. Non-self properties aggregate feedback from the field and all descendants.
Writing Feedback
Business side effects can write feedback directly:
field.selfErrors = ['Username already exists']
field.selfWarnings = ['Company email is recommended']
field.selfSuccesses = ['Passed']You can also call setSelfErrors(), setSelfWarnings(), and setSelfSuccesses(). Feedback written through these APIs uses Effect* codes, keeping it separate from validator-generated Validate* codes. The errors, warnings, and successes properties are read-only aggregates that include descendant fields and cannot be used to write feedback.
Feedback can also be queried:
field.queryFeedbacks({ type: 'error' })
field.queryFeedbacks({ code: 'ValidateError' })
field.queryFeedbacks({ address: 'username' })Form-Level Validation
Form provides aggregate validation entry points:
await form.validate()
await form.submit(async (values) => {
await request(values)
})form.validate() gathers data fields from the field tree and dispatches field validation. form.submit() validates first, then passes form values to the submit callback.
form.errors
form.warnings
form.successes
form.validFor lower-level validation registry APIs, see FormValidatorRegistry API.