Készítsünk egy új projektet valid néven.
ng new valid
Készítsünk egy login komponenst.
ng generate component login
Építsük az app.component.html sablonba a login komponenst:
<app-login />
A login TypeScript oldalról:
import { Component } from '@angular/core'; import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators //<-- } from '@angular/forms'; @Component({ selector: 'app-login', standalone: true, imports: [ReactiveFormsModule], templateUrl: './login.component.html', styleUrl: './login.component.css' }) export class LoginComponent { constructor(private builder : FormBuilder) {} loginForm = this.builder.group({ username: [''], password: [''] }); }
Az űrlap:
<h1>Bejelentkezés</h1> <form [formGroup]="loginForm"> <div> <label for="username">Felhasználónév</label> <input type="text" id="username" formControlName="username"> </div> <div> <label for="password">Jelszó</label> <input type="text" id="password" formControlName="password"> </div> </form>
A reaktív űrlap különböző állapotosztályokat ad form és input elemekhez.
<form class="ng-untouched ng-pristine ng-valid">
Minden input elem külön állapotosztályt kap:
<input class="ng-untouched ng-pristine ng-valid">
A következő táblázat alapján kideríthetjük milyen állapotban van az űrlapunk:
ng-pristine | Az űrlap még érintetlen eredeti. |
ng-dirty | Az űrlap már érintett, nem az eredeti. |
ng-touched | Egyszer érintve volt. |
ng-untouched | Már nem érintetlen |
ng-valid | Érvényes |
ng-invalid | Nem érvényes |
Indítsuk el a projektünket én nézzük meg az űrlapot a böngészőben. A böngészőben váltsunk a fejlesztői felületre, ott válasszuk az Elements fület.
<input class="form-control" ng-invalid> <--^^^^^^^^^^ -->
import { FormControl, FormGroup, ReactiveFormsModule, Validators //<-- } from '@angular/forms';
Most állítsuk be a felhasználónévhez érvényességvizsgálatot.
loginForm = this.builder.group({ username: ['', Validators.required], password: [''] });
Nézzük meg most a böngésző fejlesztői felületén az input elem állapotát. Az állapotok a következők:
form:
input username:
input password:
Használható statikus függvények a Validators osztályon.
Több információ:
Az attribútum alapján lehet egy kis piros széle, CSS-sel:
input.ng-invalid { border-left: 5px solid red; }
input.ng-valid { border-left: 5px solid green; }
Ha több érvényesítőt is megadunk, tegyük azokat egy újabb szögletes zárójelbe.
this.loginForm = this.builder.group({ username: ['', [Validators.required, Validators.minLength(3)]], password: [''] })
Kötelezőnek jelölés és email:
email: new FormControl('', [Validators.required,Validators.email])
name: new FormControl('', Validators.pattern('[a-z]'))
<small *ngIf="loginForm.controls.email.invalid">
<small *ngIf="loginForm.controls.email.invalid && loginForm.controls.email.touched">
<small *ngIf="loginForm.controls['email'].invalid">
<small *ngIf="loginForm.controls['email'].invalid && loginForm.controls['email'].touched">
@if(loginForm.controls.username.invalid){ <small>Hiba</small> }
@if( loginForm.controls.username.invalid && loginForm.controls.username.touched ){ <small>Hiba</small> }
@if( loginForm.controls['username'].errors?.['required'] && loginForm.controls['username'].touched ){ <small>Kötelező kitölteni</small> } @if( loginForm.controls['username'].errors?.['minlength'] && loginForm.controls['username'].touched ){ <small>Minimum 3 karakter</small> }
ng generate directive shared/forbiddenName
import { Directive } from '@angular/core'; import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; @Directive({ selector: '[appForbiddenName]', standalone: true }) export class ForbiddenNameDirective{ static validate(forbiddenName: RegExp): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { const forbidden = /admin/.test(control.value); return forbidden ? { 'forbiddenName': { value: control.value } } : null; } } }
loginForm = this.builder.group({ username: ['', [ Validators.required, Validators.minLength(3), ForbiddenNameDirective.validate(/admin/i) ]], password: [''] });
@if( loginForm.controls['username'].errors?.['forbiddenName'] && loginForm.controls['username'].touched ){ <small>Admin nem megengedett</small> }
ng generate directive shared/forbiddenName
A generált állományban találunk egy előre létrehozott osztályt. Az egész állomány tartalmát törölhetjük. Új tartalom:
import { AbstractControl, ValidationErrors, ValidatorFn } from "@angular/forms"; export function forbiddenNameValidator(forbiddenName: RegExp): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { const forbidden = forbiddenName.test(control.value); return forbidden ? { 'forbiddenName': { value: control.value } } : null; } }
import { forbiddenNameValidator } from './shared/forbidden-name-validator.directive'; //... ngOnInit() { this.employeeForm = this.formBuilder.group({ name: ['', [ Validators.required, Validators.minLength(3), forbiddenNameValidator(/admin/i) ]], city: [''], salary: [''] }) }
Megtiltjuk az admin név beírását.
HTML sablonban reagálunk az ilyen hibákra:
@if(employeeForm.controls['name'].errors?.['forbiddenName']) { <span>A név nem megengedett.</span> }
Validátor generálása:
ng generate directive shared/forbiddenNameValidator
import { Directive } from '@angular/core'; import { AbstractControl, ValidationErrors, Validator } from '@angular/forms'; @Directive({ selector: '[forbiddenNameValidator]', standalone: true }) export class ForbiddenNameValidatorDirective implements Validator { constructor() { } validate(control: AbstractControl): ValidationErrors | null { const forbidden = /admin/.test(control.value); return forbidden ? { 'forbiddenName': { value: control.value } } : null; } }
Használat:
loginForm = this.builder.group({ username: ['', [ Validators.required, Validators.minLength(3), new ForbiddenNameValidatorDirective ]],
Segítő szöveg:
@if( loginForm.controls['username'].errors?.['forbiddenName'] && loginForm.controls['username'].touched ){ <small>Admin nem megengedett</small> }
Minta jelszó érvényesítéshez:
const pattern = '^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{8,}$';
Megkövetelejük:
import { Component } from '@angular/core'; import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; @Component({ selector: 'app-login', standalone: true, imports: [ReactiveFormsModule], templateUrl: './login.component.html', styleUrl: './login.component.css' }) export class LoginComponent { loginForm !: FormGroup; constructor( private builder: FormBuilder ) { } ngOnInit(): void { const pattern = '^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{8,}$'; this.loginForm = this.builder.group({ name: [''], password: ['', Validators.pattern(pattern)] }); } login() { console.log(this.loginForm.value); } }