Skip to main content

Validators

Validators enforce format constraints on model fields at the data layer. They implement the IValidator interface (validate($value) : boolean) and are attached to properties via the validator option in @Property.

Packages: PropertyValidator and IValidator are in io-oidis-commons; the concrete validators live in io-oidis-hub-gui DAO/Validators/.

Built-in Validators​

ValidatorPurposeExample Usage
PropertyValidatorDefault validator — accepts every valueUsed when no validator is set
EmailValidatorEmail format validationvalidator: new EmailValidator()
PhoneValidatorPhone number format validation (spaces and dashes are ignored)validator: new PhoneValidator()
RegexValidatorMatch against a custom regex patternvalidator: new RegexValidator(/^[A-Z]{3}$/)
RangeValidatorMin/max range checkvalidator: new RangeValidator<number>(0, 100)
EnumValidatorValue must match an enum valuevalidator: new EnumValidator(StatusEnum)
PasswordValidatorPassword strength rules (PasswordRule flags, length 8–30 by default)validator: new PasswordValidator()

All regex-based validators (RegexValidator, EmailValidator, PhoneValidator, EnumValidator, PasswordValidator) and RangeValidator pass empty values by default. RegexValidator and RangeValidator accept an optional last $allowEmpty argument to reject them.

Required Fields​

required is not a validator. It is emitted into the generated Mongoose schema and enforced when the document is saved. required defaults to true — every optional field must be declared required: false:

@Property({type: String})                   // required — Save() fails when missing
public declare Name : string;

@Property({type: String, required: false}) // optional
public declare Note : string;

Validate() does not report missing required fields — the default PropertyValidator returns true for any value.

Usage​

EmailValidator​

import { EmailValidator } from "@io-oidis-hub-gui/Io/Oidis/Hub/Gui/DAO/Validators/EmailValidator.js";

@Property({type: String, validator: new EmailValidator()})
public declare Email : string;

PhoneValidator​

import { PhoneValidator } from "@io-oidis-hub-gui/Io/Oidis/Hub/Gui/DAO/Validators/PhoneValidator.js";

@Property({type: String, required: false, validator: new PhoneValidator()})
public declare Phone : string;

RegexValidator​

Match a field against any custom regular expression:

import { RegexValidator } from "@io-oidis-hub-gui/Io/Oidis/Hub/Gui/DAO/Validators/RegexValidator.js";

// Czech ZIP code format (5 digits, optional space after 3rd)
@Property({type: String, required: false, validator: new RegexValidator(/^\d{3}\s?\d{2}$/)})
public declare Zip : string;

// Product code format (3 uppercase letters, dash, 4 digits); empty value rejected
@Property({type: String, validator: new RegexValidator(/^[A-Z]{3}-\d{4}$/, false)})
public declare ProductCode : string;

RangeValidator​

Range with min and max (the constructor throws when min >= max):

import { RangeValidator } from "@io-oidis-hub-gui/Io/Oidis/Hub/Gui/DAO/Validators/RangeValidator.js";

@Property({type: Number, required: false, validator: new RangeValidator<number>(0, 100)})
public declare Percentage : number;

@Property({type: Number, required: false, validator: new RangeValidator<number>(18, 150)})
public declare Age : number;

EnumValidator​

Ensures the value matches one of the enum's values:

import { EnumValidator } from "@io-oidis-hub-gui/Io/Oidis/Hub/Gui/DAO/Validators/EnumValidator.js";

@Property({type: String, validator: new EnumValidator(RecordStatus)})
public declare Status : string;
EnumValidator is not anchored

EnumValidator builds the pattern (A)|(B)|… without ^…$, so any value that merely contains an enum value passes. Use a RegexValidator with an anchored pattern when an exact match matters.

Triggering Validation​

Model-Level Validation​

const record : Product = new Product();
record.Code = "abc";

const isValid : boolean = record.Validate(); // synchronous; runs the property validators
const findings : string[] = record.ValidateDeep(); // symbols of invalid properties, including nested models

await record.Save(); // runs Validate() first (unless skipValidation), then the schema's required checks

With $verbose (default true) every failed property is logged via LogIt.Info with the property symbol and value. There are no localized validation messages — user-facing messages are produced by the GUI.

UI-Level Validation​

Model validators run on the backend during Save() or when explicitly called. For frontend form validation, use the TextField validation API (see Events and Validation):

// Panel constructor
this.emailInput.Required(true);
this.emailInput.SetValidator(($value : string) : boolean => new EmailValidator().validate($value));

// Controller — before saving
if (!$instance.emailInput.Validate()) {
$instance.emailInput.InvalidFeedback("Enter a valid e-mail"); // text of the sibling .invalid-feedback element
return;
}

See also: Models Overview | Converters | Backend vs Frontend Models