[[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)