From 85226e609442d8dcf79a10de9f4a6d4ffee7fe54 Mon Sep 17 00:00:00 2001 From: Sercan Yemen Date: Thu, 28 Jun 2018 20:11:36 +0300 Subject: [PATCH] Fixed: Changing 'password' field while 'passwordConfirm' field is filled doesn't trigger the 'confirmPassword' validator Simplified the class and the template as we don't need an extra object for errors Used native .hasError checks on template --- .../register-2/register-2.component.html | 13 +-- .../register-2/register-2.component.ts | 80 +++++-------------- .../register/register.component.html | 13 +-- .../register/register.component.ts | 76 +++++------------- .../reset-password-2.component.html | 11 +-- .../reset-password-2.component.ts | 76 +++++------------- .../reset-password.component.html | 11 +-- .../reset-password.component.ts | 78 +++++------------- 8 files changed, 105 insertions(+), 253 deletions(-) diff --git a/src/app/main/pages/authentication/register-2/register-2.component.html b/src/app/main/pages/authentication/register-2/register-2.component.html index ed067ad3..549cfada 100644 --- a/src/app/main/pages/authentication/register-2/register-2.component.html +++ b/src/app/main/pages/authentication/register-2/register-2.component.html @@ -32,34 +32,35 @@ - + Name is required - + Email is required - + Please enter a valid email address - + Password is required - + Password confirmation is required - + Passwords must match diff --git a/src/app/main/pages/authentication/register-2/register-2.component.ts b/src/app/main/pages/authentication/register-2/register-2.component.ts index 5ef53f56..fac699d1 100644 --- a/src/app/main/pages/authentication/register-2/register-2.component.ts +++ b/src/app/main/pages/authentication/register-2/register-2.component.ts @@ -1,5 +1,5 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; -import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { AbstractControl, FormBuilder, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -15,17 +15,10 @@ import { fuseAnimations } from '@fuse/animations'; export class Register2Component implements OnInit, OnDestroy { registerForm: FormGroup; - registerFormErrors: any; // Private private _unsubscribeAll: Subject; - /** - * Constructor - * - * @param {FuseConfigService} _fuseConfigService - * @param {FormBuilder} _formBuilder - */ constructor( private _fuseConfigService: FuseConfigService, private _formBuilder: FormBuilder @@ -46,14 +39,6 @@ export class Register2Component implements OnInit, OnDestroy } }; - // Set the defaults - this.registerFormErrors = { - name : {}, - email : {}, - password : {}, - passwordConfirm: {} - }; - // Set the private defaults this._unsubscribeAll = new Subject(); } @@ -71,14 +56,16 @@ export class Register2Component implements OnInit, OnDestroy name : ['', Validators.required], email : ['', [Validators.required, Validators.email]], password : ['', Validators.required], - passwordConfirm: ['', [Validators.required, confirmPassword]] + passwordConfirm: ['', [Validators.required, confirmPasswordValidator]] }); - this.registerForm.valueChanges + // Update the validity of the 'passwordConfirm' field + // when the 'password' field changes + this.registerForm.get('password').valueChanges .pipe(takeUntil(this._unsubscribeAll)) .subscribe(() => { - this.onRegisterFormValuesChanged(); - }); + this.registerForm.get('passwordConfirm').updateValueAndValidity(); + }); } /** @@ -90,48 +77,19 @@ export class Register2Component implements OnInit, OnDestroy this._unsubscribeAll.next(); this._unsubscribeAll.complete(); } - - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * On form values changed - */ - onRegisterFormValuesChanged(): void - { - for ( const field in this.registerFormErrors ) - { - if ( !this.registerFormErrors.hasOwnProperty(field) ) - { - continue; - } - - // Clear previous errors - this.registerFormErrors[field] = {}; - - // Get the control - const control = this.registerForm.get(field); - - if ( control && control.dirty && !control.valid ) - { - this.registerFormErrors[field] = control.errors; - } - } - } } /** - * Confirm password + * Confirm password validator * * @param {AbstractControl} control - * @returns {{passwordsNotMatch: boolean}} + * @returns {ValidationErrors | null} */ -function confirmPassword(control: AbstractControl): any -{ +export const confirmPasswordValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => { + if ( !control.parent || !control ) { - return; + return null; } const password = control.parent.get('password'); @@ -139,18 +97,18 @@ function confirmPassword(control: AbstractControl): any if ( !password || !passwordConfirm ) { - return; + return null; } if ( passwordConfirm.value === '' ) { - return; + return null; } - if ( password.value !== passwordConfirm.value ) + if ( password.value === passwordConfirm.value ) { - return { - passwordsNotMatch: true - }; + return null; } -} + + return {'passwordsNotMatching': true}; +}; diff --git a/src/app/main/pages/authentication/register/register.component.html b/src/app/main/pages/authentication/register/register.component.html index 7e0ad465..03b37ed5 100644 --- a/src/app/main/pages/authentication/register/register.component.html +++ b/src/app/main/pages/authentication/register/register.component.html @@ -14,34 +14,35 @@ - + Name is required - + Email is required - + Please enter a valid email address - + Password is required - + Password confirmation is required - + Passwords must match diff --git a/src/app/main/pages/authentication/register/register.component.ts b/src/app/main/pages/authentication/register/register.component.ts index aebc79a0..b201cfcd 100644 --- a/src/app/main/pages/authentication/register/register.component.ts +++ b/src/app/main/pages/authentication/register/register.component.ts @@ -1,10 +1,10 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; -import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { AbstractControl, FormBuilder, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/internal/operators'; import { FuseConfigService } from '@fuse/services/config.service'; import { fuseAnimations } from '@fuse/animations'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/internal/operators'; @Component({ selector : 'register', @@ -15,7 +15,6 @@ import { takeUntil } from 'rxjs/internal/operators'; export class RegisterComponent implements OnInit, OnDestroy { registerForm: FormGroup; - registerFormErrors: any; // Private private _unsubscribeAll: Subject; @@ -40,14 +39,6 @@ export class RegisterComponent implements OnInit, OnDestroy } }; - // Set the defaults - this.registerFormErrors = { - name : {}, - email : {}, - password : {}, - passwordConfirm: {} - }; - // Set the private defaults this._unsubscribeAll = new Subject(); } @@ -65,13 +56,15 @@ export class RegisterComponent implements OnInit, OnDestroy name : ['', Validators.required], email : ['', [Validators.required, Validators.email]], password : ['', Validators.required], - passwordConfirm: ['', [Validators.required, confirmPassword]] + passwordConfirm: ['', [Validators.required, confirmPasswordValidator]] }); - this.registerForm.valueChanges + // Update the validity of the 'passwordConfirm' field + // when the 'password' field changes + this.registerForm.get('password').valueChanges .pipe(takeUntil(this._unsubscribeAll)) .subscribe(() => { - this.onRegisterFormValuesChanged(); + this.registerForm.get('passwordConfirm').updateValueAndValidity(); }); } @@ -84,48 +77,19 @@ export class RegisterComponent implements OnInit, OnDestroy this._unsubscribeAll.next(); this._unsubscribeAll.complete(); } - - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * On form values changed - */ - onRegisterFormValuesChanged(): void - { - for ( const field in this.registerFormErrors ) - { - if ( !this.registerFormErrors.hasOwnProperty(field) ) - { - continue; - } - - // Clear previous errors - this.registerFormErrors[field] = {}; - - // Get the control - const control = this.registerForm.get(field); - - if ( control && control.dirty && !control.valid ) - { - this.registerFormErrors[field] = control.errors; - } - } - } } /** - * Confirm password + * Confirm password validator * * @param {AbstractControl} control - * @returns {{passwordsNotMatch: boolean}} + * @returns {ValidationErrors | null} */ -function confirmPassword(control: AbstractControl): any -{ +export const confirmPasswordValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => { + if ( !control.parent || !control ) { - return; + return null; } const password = control.parent.get('password'); @@ -133,18 +97,18 @@ function confirmPassword(control: AbstractControl): any if ( !password || !passwordConfirm ) { - return; + return null; } if ( passwordConfirm.value === '' ) { - return; + return null; } - if ( password.value !== passwordConfirm.value ) + if ( password.value === passwordConfirm.value ) { - return { - passwordsNotMatch: true - }; + return null; } -} + + return {'passwordsNotMatching': true}; +}; diff --git a/src/app/main/pages/authentication/reset-password-2/reset-password-2.component.html b/src/app/main/pages/authentication/reset-password-2/reset-password-2.component.html index eb28c43b..5fb068fb 100644 --- a/src/app/main/pages/authentication/reset-password-2/reset-password-2.component.html +++ b/src/app/main/pages/authentication/reset-password-2/reset-password-2.component.html @@ -32,27 +32,28 @@ - + Email is required - + Please enter a valid email address - + Password is required - + Password confirmation is required - + Passwords must match diff --git a/src/app/main/pages/authentication/reset-password-2/reset-password-2.component.ts b/src/app/main/pages/authentication/reset-password-2/reset-password-2.component.ts index 052beba7..e8d63786 100644 --- a/src/app/main/pages/authentication/reset-password-2/reset-password-2.component.ts +++ b/src/app/main/pages/authentication/reset-password-2/reset-password-2.component.ts @@ -1,10 +1,10 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; -import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { AbstractControl, FormBuilder, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/internal/operators'; import { FuseConfigService } from '@fuse/services/config.service'; import { fuseAnimations } from '@fuse/animations'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/internal/operators'; @Component({ selector : 'reset-password-2', @@ -15,7 +15,6 @@ import { takeUntil } from 'rxjs/internal/operators'; export class ResetPassword2Component implements OnInit, OnDestroy { resetPasswordForm: FormGroup; - resetPasswordFormErrors: any; // Private private _unsubscribeAll: Subject; @@ -40,13 +39,6 @@ export class ResetPassword2Component implements OnInit, OnDestroy } }; - // Set the defaults - this.resetPasswordFormErrors = { - email : {}, - password : {}, - passwordConfirm: {} - }; - // Set the private defaults this._unsubscribeAll = new Subject(); } @@ -61,15 +53,18 @@ export class ResetPassword2Component implements OnInit, OnDestroy ngOnInit(): void { this.resetPasswordForm = this._formBuilder.group({ + name : ['', Validators.required], email : ['', [Validators.required, Validators.email]], password : ['', Validators.required], - passwordConfirm: ['', [Validators.required, confirmPassword]] + passwordConfirm: ['', [Validators.required, confirmPasswordValidator]] }); - this.resetPasswordForm.valueChanges + // Update the validity of the 'passwordConfirm' field + // when the 'password' field changes + this.resetPasswordForm.get('password').valueChanges .pipe(takeUntil(this._unsubscribeAll)) .subscribe(() => { - this.onResetPasswordFormValuesChanged(); + this.resetPasswordForm.get('passwordConfirm').updateValueAndValidity(); }); } @@ -82,48 +77,19 @@ export class ResetPassword2Component implements OnInit, OnDestroy this._unsubscribeAll.next(); this._unsubscribeAll.complete(); } - - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * On form values changed - */ - onResetPasswordFormValuesChanged(): void - { - for ( const field in this.resetPasswordFormErrors ) - { - if ( !this.resetPasswordFormErrors.hasOwnProperty(field) ) - { - continue; - } - - // Clear previous errors - this.resetPasswordFormErrors[field] = {}; - - // Get the control - const control = this.resetPasswordForm.get(field); - - if ( control && control.dirty && !control.valid ) - { - this.resetPasswordFormErrors[field] = control.errors; - } - } - } } /** - * Confirm password + * Confirm password validator * * @param {AbstractControl} control - * @returns {{passwordsNotMatch: boolean}} + * @returns {ValidationErrors | null} */ -function confirmPassword(control: AbstractControl): any -{ +export const confirmPasswordValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => { + if ( !control.parent || !control ) { - return; + return null; } const password = control.parent.get('password'); @@ -131,18 +97,18 @@ function confirmPassword(control: AbstractControl): any if ( !password || !passwordConfirm ) { - return; + return null; } if ( passwordConfirm.value === '' ) { - return; + return null; } - if ( password.value !== passwordConfirm.value ) + if ( password.value === passwordConfirm.value ) { - return { - passwordsNotMatch: true - }; + return null; } -} + + return {'passwordsNotMatching': true}; +}; diff --git a/src/app/main/pages/authentication/reset-password/reset-password.component.html b/src/app/main/pages/authentication/reset-password/reset-password.component.html index bdb49919..164d14aa 100644 --- a/src/app/main/pages/authentication/reset-password/reset-password.component.html +++ b/src/app/main/pages/authentication/reset-password/reset-password.component.html @@ -14,27 +14,28 @@ - + Email is required - + Please enter a valid email address - + Password is required - + Password confirmation is required - + Passwords must match diff --git a/src/app/main/pages/authentication/reset-password/reset-password.component.ts b/src/app/main/pages/authentication/reset-password/reset-password.component.ts index d231c341..02726c80 100644 --- a/src/app/main/pages/authentication/reset-password/reset-password.component.ts +++ b/src/app/main/pages/authentication/reset-password/reset-password.component.ts @@ -1,5 +1,5 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; -import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { AbstractControl, FormBuilder, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -15,17 +15,10 @@ import { fuseAnimations } from '@fuse/animations'; export class ResetPasswordComponent implements OnInit, OnDestroy { resetPasswordForm: FormGroup; - resetPasswordFormErrors: any; // Private private _unsubscribeAll: Subject; - /** - * Constructor - * - * @param {FuseConfigService} _fuseConfigService - * @param {FormBuilder} _formBuilder - */ constructor( private _fuseConfigService: FuseConfigService, private _formBuilder: FormBuilder @@ -46,13 +39,6 @@ export class ResetPasswordComponent implements OnInit, OnDestroy } }; - // Set the defaults - this.resetPasswordFormErrors = { - email : {}, - password : {}, - passwordConfirm: {} - }; - // Set the private defaults this._unsubscribeAll = new Subject(); } @@ -67,15 +53,18 @@ export class ResetPasswordComponent implements OnInit, OnDestroy ngOnInit(): void { this.resetPasswordForm = this._formBuilder.group({ + name : ['', Validators.required], email : ['', [Validators.required, Validators.email]], password : ['', Validators.required], - passwordConfirm: ['', [Validators.required, confirmPassword]] + passwordConfirm: ['', [Validators.required, confirmPasswordValidator]] }); - this.resetPasswordForm.valueChanges + // Update the validity of the 'passwordConfirm' field + // when the 'password' field changes + this.resetPasswordForm.get('password').valueChanges .pipe(takeUntil(this._unsubscribeAll)) .subscribe(() => { - this.onResetPasswordFormValuesChanged(); + this.resetPasswordForm.get('passwordConfirm').updateValueAndValidity(); }); } @@ -88,48 +77,19 @@ export class ResetPasswordComponent implements OnInit, OnDestroy this._unsubscribeAll.next(); this._unsubscribeAll.complete(); } - - // ----------------------------------------------------------------------------------------------------- - // @ Public methods - // ----------------------------------------------------------------------------------------------------- - - /** - * On form values changed - */ - onResetPasswordFormValuesChanged(): void - { - for ( const field in this.resetPasswordFormErrors ) - { - if ( !this.resetPasswordFormErrors.hasOwnProperty(field) ) - { - continue; - } - - // Clear previous errors - this.resetPasswordFormErrors[field] = {}; - - // Get the control - const control = this.resetPasswordForm.get(field); - - if ( control && control.dirty && !control.valid ) - { - this.resetPasswordFormErrors[field] = control.errors; - } - } - } } /** - * Confirm password + * Confirm password validator * * @param {AbstractControl} control - * @returns {{passwordsNotMatch: boolean}} + * @returns {ValidationErrors | null} */ -function confirmPassword(control: AbstractControl): any -{ +export const confirmPasswordValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => { + if ( !control.parent || !control ) { - return; + return null; } const password = control.parent.get('password'); @@ -137,18 +97,18 @@ function confirmPassword(control: AbstractControl): any if ( !password || !passwordConfirm ) { - return; + return null; } if ( passwordConfirm.value === '' ) { - return; + return null; } - if ( password.value !== passwordConfirm.value ) + if ( password.value === passwordConfirm.value ) { - return { - passwordsNotMatch: true - }; + return null; } -} + + return {'passwordsNotMatching': true}; +};