diff --git a/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.html b/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.html new file mode 100644 index 0000000..83e779b --- /dev/null +++ b/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.html @@ -0,0 +1,7 @@ + +
+ +
diff --git a/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.scss b/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.scss new file mode 100644 index 0000000..8120eb3 --- /dev/null +++ b/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.scss @@ -0,0 +1,20 @@ +.password-input { + padding: 0; + color: #696969; + position: relative; + display: flex; + align-items: center; + + input { + border: none; + padding-left: 35px; + text-align: center; + } + + .password-eye { + position: absolute; + flex: 1 1 auto; + cursor: pointer; + } +} + diff --git a/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.spec.ts b/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.spec.ts new file mode 100644 index 0000000..da706fb --- /dev/null +++ b/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.spec.ts @@ -0,0 +1,48 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PasswordInputComponent } from './password-input.component'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +describe('Component: PasswordInputComponent', () => { + let component: PasswordInputComponent; + let fixture: ComponentFixture; + let element: any; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [FormsModule, ReactiveFormsModule], + declarations: [PasswordInputComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PasswordInputComponent); + component = fixture.componentInstance; + element = fixture.nativeElement; + fixture.detectChanges(); + }); + + it('should change input type with a click on the icon', () => { + expect(element.querySelector('input').type).toBe('password'); + + element.querySelector('i').click(); + fixture.detectChanges(); + expect(element.querySelector('input').type).toBe('text'); + + element.querySelector('i').click(); + fixture.detectChanges(); + expect(element.querySelector('input').type).toBe('password'); + }); + + it('should change an icon with a click on it', () => { + expect(element.querySelector('i').classList).toContain('fa-eye'); + + element.querySelector('i').click(); + fixture.detectChanges(); + expect(element.querySelector('i').classList).toContain('fa-eye-slash'); + + element.querySelector('i').click(); + fixture.detectChanges(); + expect(element.querySelector('i').classList).toContain('fa-eye'); + }); +}); diff --git a/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.ts b/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.ts new file mode 100644 index 0000000..ae8b279 --- /dev/null +++ b/projects/ng-rocketparts/src/lib/components/password-input/password-input.component.ts @@ -0,0 +1,93 @@ +import { + Component, + ElementRef, + forwardRef, + HostBinding, + Input, + OnInit +} from '@angular/core'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; + +export const PASSWORD_INPUT_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => PasswordInputComponent), // tslint:disable-line + multi: true +}; + +@Component({ + selector: 'ngr-password-input', + templateUrl: './password-input.component.html', + styleUrls: ['./password-input.component.scss'], + providers: [PASSWORD_INPUT_VALUE_ACCESSOR] +}) +export class PasswordInputComponent implements OnInit, ControlValueAccessor { + @HostBinding('class.ngr-password-input') + passwordInputClass = true; + + @Input() + placeholder: string; + + @Input() + paddingLeft: number; + + onChange: () => void; + + onTouched: () => void; + + input: any; + + displayValue: string; + + disabled: boolean; + + show: boolean; + + constructor(private elem: ElementRef) {} + + ngOnInit() { + this.input = this.elem.nativeElement.querySelector('input'); + this.show = this.input.type === 'password'; + } + + registerOnChange(fn: any): void { + this.onChange = () => { + if (fn) { + fn(this.displayValue); + } + }; + } + + registerOnTouched(fn: any): void { + this.onTouched = fn; + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + } + + writeValue(value: any): void { + if (this.displayValue !== value) { + this.displayValue = value; + } + } + + /** + * Called when the selection changed + * @param value + */ + onInputChange(value: string) { + this.displayValue = value; + if (this.onChange) { + this.onChange(); + } + } + + /** + * Allows to show and hide password + * @param {Event} e + */ + toggle(e: Event) { + this.show = !this.show; + this.input.type = this.input.type === 'password' ? 'text' : 'password'; + } +} diff --git a/projects/ng-rocketparts/src/lib/components/password-input/password-input.module.spec.ts b/projects/ng-rocketparts/src/lib/components/password-input/password-input.module.spec.ts new file mode 100644 index 0000000..51b30a9 --- /dev/null +++ b/projects/ng-rocketparts/src/lib/components/password-input/password-input.module.spec.ts @@ -0,0 +1,13 @@ +import { PasswordInputModule } from './password-input.module'; + +describe('PasswordInputModule', () => { + let passwordInputModule: PasswordInputModule; + + beforeEach(() => { + passwordInputModule = new PasswordInputModule(); + }); + + it('should create an instance', () => { + expect(passwordInputModule).toBeTruthy(); + }); +}); diff --git a/projects/ng-rocketparts/src/lib/components/password-input/password-input.module.ts b/projects/ng-rocketparts/src/lib/components/password-input/password-input.module.ts new file mode 100644 index 0000000..bba4b41 --- /dev/null +++ b/projects/ng-rocketparts/src/lib/components/password-input/password-input.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { PasswordInputComponent } from './password-input.component'; + +@NgModule({ + imports: [CommonModule, FormsModule, ReactiveFormsModule], + declarations: [PasswordInputComponent], + exports: [PasswordInputComponent] +}) +export class PasswordInputModule {} diff --git a/projects/ng-rocketparts/src/lib/ng-rocketparts.module.ts b/projects/ng-rocketparts/src/lib/ng-rocketparts.module.ts index 7944e05..97e301e 100644 --- a/projects/ng-rocketparts/src/lib/ng-rocketparts.module.ts +++ b/projects/ng-rocketparts/src/lib/ng-rocketparts.module.ts @@ -1,9 +1,14 @@ import { NgModule } from '@angular/core'; import { MaybeAsyncPipe } from './pipes/maybe-async.pipe'; +import { PasswordInputModule } from './components/password-input/password-input.module'; +import { CommonModule } from '@angular/common'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +const MODULES = [PasswordInputModule]; @NgModule({ - imports: [], + imports: [CommonModule, FormsModule, ReactiveFormsModule], declarations: [MaybeAsyncPipe], - exports: [MaybeAsyncPipe] + exports: [...MODULES, MaybeAsyncPipe] }) export class NgRocketPartsModule {}