From e83b17dba21374b16b9bff28e9b48629f97a4888 Mon Sep 17 00:00:00 2001 From: Marc Stammerjohann Date: Wed, 10 Oct 2018 01:24:10 +0200 Subject: [PATCH] feat(password): add password component to show and hide input * enable formControlName --- projects/core/package.json | 1 + .../core/src/lib/fivethree.core.module.ts | 5 ++ projects/core/src/lib/password/README.md | 1 + .../src/lib/password/password.component.html | 5 ++ .../src/lib/password/password.component.scss | 0 .../lib/password/password.component.spec.ts | 25 ++++++ .../src/lib/password/password.component.ts | 76 +++++++++++++++++++ .../lib/router-item/router-item.component.ts | 2 - src/app/app-routing.module.ts | 3 +- src/app/app.component.ts | 5 ++ src/app/password/password.module.ts | 29 +++++++ src/app/password/password.page.html | 36 +++++++++ src/app/password/password.page.scss | 0 src/app/password/password.page.spec.ts | 27 +++++++ src/app/password/password.page.ts | 34 +++++++++ 15 files changed, 246 insertions(+), 3 deletions(-) create mode 100644 projects/core/src/lib/password/README.md create mode 100644 projects/core/src/lib/password/password.component.html create mode 100644 projects/core/src/lib/password/password.component.scss create mode 100644 projects/core/src/lib/password/password.component.spec.ts create mode 100644 projects/core/src/lib/password/password.component.ts create mode 100644 src/app/password/password.module.ts create mode 100644 src/app/password/password.page.html create mode 100644 src/app/password/password.page.scss create mode 100644 src/app/password/password.page.spec.ts create mode 100644 src/app/password/password.page.ts diff --git a/projects/core/package.json b/projects/core/package.json index 5631ebd2..5646fb27 100644 --- a/projects/core/package.json +++ b/projects/core/package.json @@ -5,6 +5,7 @@ "@angular/animations": "^6.1.9", "@angular/common": "^6.1.9", "@angular/core": "^6.1.9", + "@angular/forms": "^6.1.9", "@angular/router": "~6.1.9", "@ionic/angular": "4.0.0-beta.12" } diff --git a/projects/core/src/lib/fivethree.core.module.ts b/projects/core/src/lib/fivethree.core.module.ts index 9aaceddd..3a2680d7 100644 --- a/projects/core/src/lib/fivethree.core.module.ts +++ b/projects/core/src/lib/fivethree.core.module.ts @@ -1,3 +1,4 @@ +import { FormsModule } from '@angular/forms'; import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { IonicModule } from '@ionic/angular'; @@ -7,14 +8,17 @@ import { StepHeaderComponent } from './step-header/step-header.component'; import { StepContentComponent } from './step-content/step-content.component'; import { ExpandableComponent } from './expandable/expandable.component'; import { RouterItemComponent } from './router-item/router-item.component'; +import { PasswordComponent } from './password/password.component'; @NgModule({ imports: [ CommonModule, + FormsModule, IonicModule ], declarations: [ ExpandableComponent, + PasswordComponent, StepperComponent, StepComponent, StepHeaderComponent, @@ -23,6 +27,7 @@ import { RouterItemComponent } from './router-item/router-item.component'; ], exports: [ ExpandableComponent, + PasswordComponent, StepperComponent, StepComponent, StepHeaderComponent, diff --git a/projects/core/src/lib/password/README.md b/projects/core/src/lib/password/README.md new file mode 100644 index 00000000..c4784b20 --- /dev/null +++ b/projects/core/src/lib/password/README.md @@ -0,0 +1 @@ +# fiv-password \ No newline at end of file diff --git a/projects/core/src/lib/password/password.component.html b/projects/core/src/lib/password/password.component.html new file mode 100644 index 00000000..f1d1d052 --- /dev/null +++ b/projects/core/src/lib/password/password.component.html @@ -0,0 +1,5 @@ + + {{ placeholder }} + + + \ No newline at end of file diff --git a/projects/core/src/lib/password/password.component.scss b/projects/core/src/lib/password/password.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/projects/core/src/lib/password/password.component.spec.ts b/projects/core/src/lib/password/password.component.spec.ts new file mode 100644 index 00000000..49227f21 --- /dev/null +++ b/projects/core/src/lib/password/password.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PasswordComponent } from './password.component'; + +describe('PasswordComponent', () => { + let component: PasswordComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ PasswordComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PasswordComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/core/src/lib/password/password.component.ts b/projects/core/src/lib/password/password.component.ts new file mode 100644 index 00000000..ee48ecfa --- /dev/null +++ b/projects/core/src/lib/password/password.component.ts @@ -0,0 +1,76 @@ +import { Component, OnInit, Input, forwardRef } from '@angular/core'; +import { NG_VALUE_ACCESSOR, ControlValueAccessor, Validator, ValidationErrors, AbstractControl, NG_VALIDATORS } from '@angular/forms'; + +export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => PasswordComponent), + multi: true +}; + +export const CUSTOM_INPUT_VALIDATOR = { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => PasswordComponent), + multi: true, +}; + +@Component({ + selector: 'fiv-password', + templateUrl: './password.component.html', + styleUrls: ['./password.component.scss'], + providers: [ + CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR, + CUSTOM_INPUT_VALIDATOR + ], +}) +export class PasswordComponent implements ControlValueAccessor, OnInit, Validator { + + @Input() hideIcon = 'eye-off'; + @Input() placeholder: string; + @Input() position: 'floating' | 'inline' | 'fixed' | 'stacked' = 'floating'; + @Input() show: boolean; + @Input() showIcon = 'eye'; + @Input() clearOnEdit = false; + + private innerValue: any = ''; + private onTouchedCallback: () => {}; + private onChangeCallback: (_: any) => {}; + + constructor() { } + + ngOnInit() { + } + + toggleShowPassword() { + this.show = !this.show; + } + + get value(): any { + return this.innerValue; + } + + set value(v: any) { + if (v !== this.innerValue) { + this.innerValue = v; + this.onChangeCallback(v); + } + } + + writeValue(value: any) { + if (value !== this.innerValue) { + this.innerValue = value; + } + } + + registerOnChange(fn: any) { + this.onChangeCallback = fn; + } + + registerOnTouched(fn: any) { + this.onTouchedCallback = fn; + } + + validate(control: AbstractControl): ValidationErrors { + return null; + } + +} diff --git a/projects/core/src/lib/router-item/router-item.component.ts b/projects/core/src/lib/router-item/router-item.component.ts index 74d2c435..baf85484 100644 --- a/projects/core/src/lib/router-item/router-item.component.ts +++ b/projects/core/src/lib/router-item/router-item.component.ts @@ -42,7 +42,6 @@ export class RouterItemComponent implements OnInit { @HostBinding('class.active') get activeClass() { const isActive = (this.routeActive && this.router.url.startsWith(this.pageUrl)) || this.active; - console.log(isActive, this.active, this.router, this.pageUrl); return isActive; } @@ -52,7 +51,6 @@ export class RouterItemComponent implements OnInit { } hasShape(): boolean { - console.log(this.shape); return this.shape === 'line' || this.shape === 'dot'; } diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 6aeb5391..d99dbea8 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -11,7 +11,8 @@ const routes: Routes = [ path: 'components', loadChildren: './components/components.module#ComponentsPageModule' }, - { path: 'loading', loadChildren: './loading/loading.module#LoadingPageModule' } + { path: 'loading', loadChildren: './loading/loading.module#LoadingPageModule' }, + { path: 'password', loadChildren: './password/password.module#PasswordPageModule' } ]; @NgModule({ diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 8049053c..f76bb4a5 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -15,6 +15,11 @@ export class AppComponent { url: '/components', icon: 'home' }, + { + title: 'Password Item', + url: '/password', + icon: 'key' + }, { title: 'Loading', url: '/loading', diff --git a/src/app/password/password.module.ts b/src/app/password/password.module.ts new file mode 100644 index 00000000..49adfda3 --- /dev/null +++ b/src/app/password/password.module.ts @@ -0,0 +1,29 @@ +import { FivethreeCoreModule } from 'core'; +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { PasswordPage } from './password.page'; + +const routes: Routes = [ + { + path: '', + component: PasswordPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + FivethreeCoreModule, + ReactiveFormsModule, + RouterModule.forChild(routes) + ], + declarations: [PasswordPage] +}) +export class PasswordPageModule {} diff --git a/src/app/password/password.page.html b/src/app/password/password.page.html new file mode 100644 index 00000000..2959f71e --- /dev/null +++ b/src/app/password/password.page.html @@ -0,0 +1,36 @@ + + + password + + + + + + Default Password + + + Password with placeholder + + + Password with placeholder and inline position + + + Show password + + + Password with any show and hide icons + + + Password in form +
+ + E-Mail + + + + + Login + +
+ +
\ No newline at end of file diff --git a/src/app/password/password.page.scss b/src/app/password/password.page.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/password/password.page.spec.ts b/src/app/password/password.page.spec.ts new file mode 100644 index 00000000..768cf9e3 --- /dev/null +++ b/src/app/password/password.page.spec.ts @@ -0,0 +1,27 @@ +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PasswordPage } from './password.page'; + +describe('PasswordPage', () => { + let component: PasswordPage; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ PasswordPage ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PasswordPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/password/password.page.ts b/src/app/password/password.page.ts new file mode 100644 index 00000000..56725e8f --- /dev/null +++ b/src/app/password/password.page.ts @@ -0,0 +1,34 @@ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder, Validators, AbstractControl } from '@angular/forms'; + +@Component({ + selector: 'app-password', + templateUrl: './password.page.html', + styleUrls: ['./password.page.scss'], +}) +export class PasswordPage implements OnInit { + + loginForm: FormGroup; + + constructor(public formBuilder: FormBuilder) { } + + ngOnInit() { + this.setupForm(); + } + + setupForm() { + this.loginForm = this.formBuilder.group({ + email: ['', [Validators.email, Validators.required]], + password: ['', [Validators.minLength(6), Validators.required]], + }); + } + + get email(): AbstractControl { + return this.loginForm.get('email'); + } + + onSubmit() { + console.log(this.loginForm.value); + } + +}