Support toggle password field visibility

This commit is contained in:
shamoon 2023-11-21 21:40:11 -08:00
parent 5d4ef6f958
commit f948113c0f
4 changed files with 43 additions and 4 deletions

View File

@ -1,8 +1,15 @@
<div class="mb-3"> <div class="mb-3">
<label class="form-label" [for]="inputId">{{title}}</label> <label class="form-label" [for]="inputId">{{title}}</label>
<input #inputField type="password" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled"> <div class="input-group" [class.is-invalid]="error">
<small *ngIf="hint" class="form-text text-muted" [innerHTML]="hint | safeHtml"></small> <input #inputField [type]="showReveal && textVisible ? 'text' : 'password'" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled">
<button *ngIf="showReveal" type="button" class="btn btn-outline-secondary" (click)="toggleVisibility()" i18n-title title="Show password">
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#eye" />
</svg>
</button>
</div>
<div class="invalid-feedback"> <div class="invalid-feedback">
{{error}} {{error}}
</div> </div>
<small *ngIf="hint" class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
</div> </div>

View File

@ -5,6 +5,7 @@ import {
NG_VALUE_ACCESSOR, NG_VALUE_ACCESSOR,
} from '@angular/forms' } from '@angular/forms'
import { PasswordComponent } from './password.component' import { PasswordComponent } from './password.component'
import { By } from '@angular/platform-browser'
describe('PasswordComponent', () => { describe('PasswordComponent', () => {
let component: PasswordComponent let component: PasswordComponent
@ -33,4 +34,21 @@ describe('PasswordComponent', () => {
// fixture.detectChanges() // fixture.detectChanges()
// expect(component.value).toEqual('foo') // expect(component.value).toEqual('foo')
}) })
it('should support toggling field visibility', () => {
expect(component.inputField.nativeElement.type).toEqual('password')
component.showReveal = true
fixture.detectChanges()
fixture.debugElement.query(By.css('button')).triggerEventHandler('click')
fixture.detectChanges()
expect(component.inputField.nativeElement.type).toEqual('text')
})
it('should empty field if password is obfuscated', () => {
component.value = '*********'
component.toggleVisibility()
expect(component.value).toEqual('')
component.toggleVisibility()
expect(component.value).toEqual('*********')
})
}) })

View File

@ -1,4 +1,4 @@
import { Component, forwardRef } from '@angular/core' import { Component, Input, forwardRef } from '@angular/core'
import { NG_VALUE_ACCESSOR } from '@angular/forms' import { NG_VALUE_ACCESSOR } from '@angular/forms'
import { AbstractInputComponent } from '../abstract-input' import { AbstractInputComponent } from '../abstract-input'
@ -15,6 +15,20 @@ import { AbstractInputComponent } from '../abstract-input'
styleUrls: ['./password.component.scss'], styleUrls: ['./password.component.scss'],
}) })
export class PasswordComponent extends AbstractInputComponent<string> { export class PasswordComponent extends AbstractInputComponent<string> {
@Input()
showReveal: boolean = false
public textVisible: boolean = false
public toggleVisibility(): void {
this.textVisible = !this.textVisible
if (this.textVisible && this.value?.replace(/\*/g, '').length === 0) {
this.writeValue('')
} else if (!this.textVisible && this.value?.length === 0) {
this.writeValue('*********')
}
}
constructor() { constructor() {
super() super()
} }

View File

@ -15,7 +15,7 @@
</div> </div>
</div> </div>
</div> </div>
<pngx-input-password i18n-title title="Password" formControlName="password" (keyup)="onPasswordKeyUp($event)" [error]="error?.password"></pngx-input-password> <pngx-input-password i18n-title title="Password" formControlName="password" (keyup)="onPasswordKeyUp($event)" [showReveal]="true" [error]="error?.password"></pngx-input-password>
<div ngbAccordion> <div ngbAccordion>
<div ngbAccordionItem="first" [collapsed]="!showPasswordConfirm" class="border-0 bg-transparent"> <div ngbAccordionItem="first" [collapsed]="!showPasswordConfirm" class="border-0 bg-transparent">
<div ngbAccordionCollapse> <div ngbAccordionCollapse>