Change password view enhancement to support and display password validations
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
<mat-form-field>
|
||||
<mat-label>{{ label }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[disabled]="disabled"
|
||||
[errorStateMatcher]="matcher"
|
||||
(focusout)="onFocusOut()"
|
||||
(input)="onInput($event)"
|
||||
[required]="required"
|
||||
[type]="type"
|
||||
[value]="value"
|
||||
/>
|
||||
<mat-icon matSuffix (click)="onVisibilityClick($event)">{{ icon }}</mat-icon>
|
||||
<mat-error *ngIf="ngControl.hasError('required')">{{ label }} is a required field.</mat-error>
|
||||
<mat-error *ngIf="ngControl.hasError(customErrorName)">{{ customErrorMessage }}</mat-error>
|
||||
</mat-form-field>
|
||||
@@ -0,0 +1,11 @@
|
||||
:host {
|
||||
width: 100%;
|
||||
|
||||
mat-icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.mat-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { InputPasswordComponent } from './input-password.component';
|
||||
|
||||
describe('InputPasswordComponent', () => {
|
||||
let component: InputPasswordComponent;
|
||||
let fixture: ComponentFixture<InputPasswordComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [InputPasswordComponent]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(InputPasswordComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,114 @@
|
||||
import { Component, Input, Optional, Self, ViewChild } from '@angular/core';
|
||||
import {
|
||||
AbstractControl,
|
||||
ControlValueAccessor,
|
||||
FormGroupDirective,
|
||||
NgControl,
|
||||
NgForm,
|
||||
Validators
|
||||
} from '@angular/forms';
|
||||
import { MatInput } from '@angular/material/input';
|
||||
import { ErrorStateMatcher } from '@angular/material/core';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-input-password',
|
||||
templateUrl: './input-password.component.html',
|
||||
styleUrls: ['./input-password.component.scss']
|
||||
})
|
||||
export class InputPasswordComponent implements ControlValueAccessor, ErrorStateMatcher {
|
||||
disabled = false;
|
||||
|
||||
icon = 'visibility_off';
|
||||
|
||||
@Input()
|
||||
label: string = null;
|
||||
|
||||
@Input()
|
||||
customErrorMessage: string = null;
|
||||
|
||||
@Input()
|
||||
customErrorName: string = null;
|
||||
|
||||
get matcher() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@ViewChild(MatInput)
|
||||
matInput: MatInput;
|
||||
|
||||
get required(): boolean {
|
||||
return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;
|
||||
}
|
||||
|
||||
@Input()
|
||||
set required(value: boolean) {
|
||||
this._required = value;
|
||||
}
|
||||
|
||||
touched = false;
|
||||
|
||||
type = 'password';
|
||||
|
||||
value: string = null;
|
||||
|
||||
private _required: boolean = null;
|
||||
|
||||
private _visible = false;
|
||||
|
||||
constructor(@Optional() @Self() public ngControl: NgControl) {
|
||||
if (ngControl !== null) {
|
||||
ngControl.valueAccessor = this;
|
||||
}
|
||||
}
|
||||
|
||||
isErrorState(control: AbstractControl | null, form: FormGroupDirective | NgForm | null): boolean {
|
||||
return this.touched && (this.ngControl?.control?.invalid ?? false);
|
||||
}
|
||||
|
||||
onChange = (value: any) => {};
|
||||
|
||||
onFocusOut(): void {
|
||||
this.touched = true;
|
||||
this.onTouched();
|
||||
this.matInput.updateErrorState();
|
||||
}
|
||||
|
||||
onInput($event: any): void {
|
||||
this.value = $event.currentTarget.value;
|
||||
this.touched = true;
|
||||
this.onChange(this.value);
|
||||
}
|
||||
|
||||
onTouched = () => {};
|
||||
|
||||
onVisibilityClick($event: Event): void {
|
||||
if (this._visible) {
|
||||
this.icon = 'visibility_off';
|
||||
this.type = 'password';
|
||||
} else {
|
||||
this.icon = 'visibility';
|
||||
this.type = 'text';
|
||||
}
|
||||
|
||||
// Invert the value.
|
||||
this._visible = !this._visible;
|
||||
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
registerOnChange(fn: any) {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: any) {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
this.disabled = isDisabled;
|
||||
}
|
||||
|
||||
writeValue(obj: any): void {
|
||||
this.value = obj;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user