[[oktatas:web:angular|< Angular]]
====== Angular - Űrlapok érvényessége ======
* **Szerző:** Sallai András
* Copyright (c) 2022, Sallai András
* Szerkesztve: 2022, 2024, 2025
* Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC Attribution-Share Alike 4.0 International]]
* Web: https://szit.hu
===== Kezdő projekt =====
Készítsünk egy új projektet **valid** néven.
ng new valid
Készítsünk egy login komponenst.
cd valid
ng generate component login
Importálnunk kell a LoginComponent a TypeScript oldalon. A **app.component.ts** fájlban:
import { LoginComponent } from './login/login.component';
//...
imports: [LoginComponent],
//...
Építsük az **app.component.html** sablonba a login komponenst:
===== A login űrlap =====
Készítsük el a beléptető felületet.
Kezdjük a TypeScript oldalon. A login.component.ts fájlban importáljuk a **FormBuilder** és a **ReactiveFormsModule** modulokat. A ReactiveFormsModule-t a dekorátorban is importálni kell.
import {
FormBuilder,
ReactiveFormsModule
} from '@angular/forms';
//...
imports: [ReactiveFormsModule],
Injektáljuk a FormBuilder modult a konstruktorban, hogy használható legyen:
constructor(private builder: FormBuilder) { }
Készítsük el a **loginForm** objektumot.
loginForm = this.builder.group({
username: [''],
password: ['']
})
Kezdjük a HTML sablonban egy form elemmel:
Egészítsük ki beviteli mezőkkel:
A teljes kód:
import { Component } from '@angular/core';
import {
FormBuilder,
ReactiveFormsModule
} 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:
Bejelentkezés
===== Állapotosztályok =====
A reaktív űrlap különböző állapotosztályokat ad form és input elemekhez.
Minden input elem külön állapotosztályt kap:
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.
<--^^^^^^^^^^ -->
===== Érvényességhez szükséges modul =====
Az érvényesség ellenőrzéséhez szükségünk van a Validators modulra.
import {
FormBuilder
ReactiveFormsModule,
Validators //<--
} from '@angular/forms';
===== Felhasználónév megkövetelése =====
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:
* ng-untouched
* ng-pristine
* ng-invalid ⇦
input username:
* ng-untouched
* ng-pristine
* ng-invalid ⇦
input password:
* ng-untouched
* ng-pristine
* ng-valid
===== Validátorok =====
Használható statikus függvények a Validators osztályon.
* min()
* max()
* required()
* requiredTrue()
* email()
* minLength()
* maxLength()
* patter(sztring)
* nullValidator()
* compose()
* composeAsync()
Több információ:
* https://angular.dev/api/forms/Validators
===== CSS kiemelések =====
Az attribútum alapján lehet egy kis piros széle, CSS-sel. A login.component.css fájlban
állítsuk be:
input.ng-invalid {
border-left: 5px solid red;
}
input.ng-valid {
border-left: 5px solid green;
}
Egyszerre ng-invalid és ng-touched attribútum elvárás:
input.ng-invalid.ng-touched {
border: 3px solid red;
}
input.ng-valid {
border: 3px solid lightgreen;
}
===== Több érvényesítő =====
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: ['']
})
===== E-mail =====
Kötelezőnek jelölés és email:
email: new FormControl('', [Validators.required,Validators.email])
===== Minta használata =====
name: new FormControl('', Validators.pattern('[a-z]'))
===== Segítő szöveg =====
==== Angular 12.x ====
==== Angular 13.x ====
==== Angular 19.x ====
@if(loginForm.controls.username.invalid){
Hiba
}
@if(
loginForm.controls.username.invalid &&
loginForm.controls.username.touched
){
Hiba
}
===== A követelmények szétválasztása =====
@if(
loginForm.controls['username'].errors?.['required']
&& loginForm.controls['username'].touched
){
Kötelező kitölteni
}
@if(
loginForm.controls['username'].errors?.['minlength']
&& loginForm.controls['username'].touched
){
Minimum 3 karakter
}
===== Saját érvényesítő =====
Egy direktívát fogunk létrehozni forbiddenName elnevezéssel, ahol az admin nevet nem engedjük meg.
ng generate directive shared/forbiddenName
A következő fájlok jönnek létre:
* src/shared/forbidden-name.directive.spec.ts
* src/shared/forbidden-name.directive.ts
A .ts fájl tartalmát írjuk át így:
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;
}
}
}
==== Használat ====
loginForm = this.builder.group({
username: ['', [
Validators.required,
Validators.minLength(3),
ForbiddenNameDirective.validate(/admin/i)
]],
password: ['']
});
==== Segítő üzenet ====
@if(
loginForm.controls['username'].errors?.['forbiddenName']
&& loginForm.controls['username'].touched
){
Admin nem megengedett
}
==== Lásd még ====
* https://angular.dev/api/forms/Validator
===== Saját érvényesítő függvénnyel =====
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;
}
}
=== Az érvényesítő használata ===
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']) {
A név nem megengedett.
}
===== Saját érvényesítő 3 =====
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
){
Admin nem megengedett
}
===== Jelszó érvényessége =====
Minta jelszó érvényesítéshez:
const pattern = '^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)[A-Za-z\\d]{8,}$';
Megkövetelejük:
* legyen benne nagybetű (az első zárójeles rész)
* legyen benne kisbetű (a második zárójeles rész)
* legyen benne szám (a harmadik zárójeles rész)
* csak nagy vagy kisbetű és szám lehet (a szögletes zárójel)
* minimum 8 (a kapcsos zárójel)
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);
}
}
Példa ha csak kisbetűket fogadunk el, de annak kötelezően lennie kell:
Validators.pattern(/^(?=.*[a-z])[a-z]+$/)
Csak kisbetűk és számok:
Validators.pattern(/^(?=.*[a-z])(?=.*[0-9])[a-z0-9]+$/)
Vagy:
Validators.pattern(/^(?=.*[a-z0-9])[a-z0-9]+$/)
Jelszavakhoz több követelmény Validators osztállyal:
password: ['', [
Validators.required,
Validators.minLength(6),
Validators.maxLength(12),
Validators.pattern(/^(?=.*[a-z])(?=.*[0-9])[a-z0-9]+$/)
]],
===== Kattintás =====
export class LoginComponent {
//...
onSubmit() {
console.log(this.loginForm.value);
}
}
===== Források =====
* https://angular.dev/cli/generate/directive (2024)
* https://v18.angular.dev/guide/forms/form-validation (2024)