valdr-ng
v1.6.0
Published
Library for creating Angular reactive form configuration.
Downloads
26
Readme
ValdrNG
Angular reactive forms util which generates configuration and validators for constraints.
Inspired by Valdr for AngularJS.
Why ValdrNG?
Angular form creation and creating validators manually for each field for a model is too much boilerplate code. Having a configuration and a service which creates reactive form configuration helps to cut down on manual form creation, which is especially useful when working with large and complex forms.
Very similar to Valdr for AngularJS, there are few more advantages to this:
- Less form creation boilerplate
- Possibility to generate the constraints from the models that are present on your back-end (see valdr-bean-validation for Java)
- Compliant with Angular Reactive Forms
- Easy extension with custom validators
Getting started
- Install
ValdrNg
NPM
npm i valdr-ng
Yarn
yarn install valdr-ng
- Register the
ValdrNgModule
in the application module.
@NgModule({
imports: [ValdrNgModule],
})
export class AppModule {}
- Set the constraints
export class AppModule {
constructor(private valdrNgService: ValdrNgService) {
valdrNgService.setConstraints({
Person: {
firstName: {
required: {
message: 'First name is required.',
},
size: {
min: 2,
max: 20,
message: 'First name must be between 2 and 20 characters.',
},
},
username: {
pattern: {
value: '[a-zA-Z]{4,}',
message:
"Username must be longer than 4 characters and match 'a-zA-Z'.",
},
},
},
});
}
}
- Use it to: 4.1. create form configuration from the model and model name:
class MyComponent implements OnInit {
personForm: FormGroup;
person = {
firstName: 'John',
username: '',
};
constructor(
private valdrNgService: ValdrNgService,
private fb: FormBuilder
) {}
ngOnInit(): void {
const controls = this.valdrNgService.createFormGroupControls(
this.person,
'Person'
);
this.personForm = this.fb.group(controls);
}
}
class MyComponent implements OnInit {
personForm: FormGroup;
person = {
firstName: 'John',
username: '',
};
constructor(
private valdrNgService: ValdrNgService,
private fb: FormBuilder
) {}
ngOnInit(): void {
const controls = this.fb.group({
firstName: [this.person.firstName],
username: [this.person.username, [Validators.required]],
});
this.personForm = this.fb.group(controls);
this.valdrNgService.addValidators(this.personForm, 'Person');
}
}
- The form is ready, now we can show messages for the fields
<form [formGroup]="personForm">
<label for="firstName">First name:</label>
<input id="firstName" formControlName="firstName" />
<!-- Simple error handling -->
<div *ngIf="personForm.get('firstName')?.errors as err">
<p *ngIf="err['required'] as req">{{req.message}}</p>
</div>
<label for="username">Username:</label>
<input id="username" formControlName="username" />
<!-- Other error handling component -->
</form>
Constraints JSON
The JSON object which defines the validation rules has the following structure:
{
"TypeName": {
"ValidatorName": {
"message": "My Error Message"
}
}
}
- TypeName - The type of the object
- FieldName - The field name
- ValidatorName - Name of the validator
- message - The message which should be attached on the validation error
Note: The ValidatorName
object can contain other validator arguments besides message
.
Example:
{
"Person": {
"firstName": {
"required": {
"message": "First name is required."
},
"size": {
"min": 2,
"max": 20,
"message": "First name must be between 2 and 20 characters."
}
},
"username": {
"pattern": {
"value": "[a-zA-Z]{4,}",
"message": "Username must be longer than 4 characters and match 'a-zA-Z'."
}
}
}
}
Validators
Built-in validators:
- size
- min
- max
- minLength
- maxLength
- pattern
- url
NOTE: For more details on the built-in validators see the Built-in validators section below.
Custom validator
- Create a validator by overriding
BaseValidatorFactory
:
@Injectable()
class MyValidator extends BaseValidatorFactory {
getConstraintName() {
return 'validByValue';
}
createValidator(config: {
value: string;
message: string;
}): ValdrValidationFn {
const validateFn = ({
value,
}: AbstractControl): ValidationErrors | null => {
if (value === null || value === config.value) {
return null;
}
return {
[this.getConstraintName()]: {
message: config.message,
},
};
};
return validateFn;
}
}
- Register it in
ValdrNgModule
orValdrNgService
:
- In the module
@NgModule({
imports: [ValdrNgModule.forRoot([MyValidator])],
})
export class AppModule {}
- Directly in the service
@NgModule({
imports: [ValdrNgModule],
providers: [MyValidator],
})
export class AppModule {
constructor(valdrNgService: ValdrNgService, myValidator: MyValidator) {
valdrNgService.addValidatorFactories([myValidator]);
}
}
- Use it in constraints:
export class AppModule {
constructor(valdrNgService: ValdrNgService, myValidator: MyValidator) {
valdrNgService.addValidatorFactories([myValidator]);
valdrNgService.setConstraints({
Person: {
password: {
validByValue: {
value: 'p455w0rd',
message: 'Invalid password!',
},
},
},
});
}
}
How it is integrated with Angular Forms
ValdrNG uses the provided Angular validators
and wraps them by validator name, and returning the message
along with the validation result.
That makes couple of things easier:
- Migration of the current forms to ValdrNG (validation result is extended)
- Easily accessible a dedicated message for each field (see the usage)
Built-in validators
- size - Validates field size
{
size: {
min: number;
max: number;
message: string;
}
}
- min - Minimum numeric value
{
min: {
value: number;
message: string;
}
}
- max - Maximum numeric value
{
max: {
value: number;
message: string;
}
}
- minLength - Minimum length of a string
{
minLength: {
value: number;
message: string;
}
}
- maxLength - Maximum length of a string
{
maxLength: {
value: number;
message: string;
}
}
- email - Checks for valid e-mail.
{
email: {
message: string;
}
}
- pattern - Validates by the given pattern
{
pattern: {
value: string;
message: string;
}
}
- url - Checks if the field has valid URL, currently supports urls starting with http, https & ftp.
{
url: {
message: string;
}
}