diff --git a/projects/ng-password-validator-dev/src/app/app.component.html b/projects/ng-password-validator-dev/src/app/app.component.html
index 3fdc7a2..5ff7398 100644
--- a/projects/ng-password-validator-dev/src/app/app.component.html
+++ b/projects/ng-password-validator-dev/src/app/app.component.html
@@ -6,7 +6,12 @@
-
+
+
+
+
+
diff --git a/projects/ng-password-validator-dev/src/app/app.component.scss b/projects/ng-password-validator-dev/src/app/app.component.scss
index 59e91e2..15687e5 100644
--- a/projects/ng-password-validator-dev/src/app/app.component.scss
+++ b/projects/ng-password-validator-dev/src/app/app.component.scss
@@ -52,7 +52,7 @@ p {
.content {
display: flex;
- margin: 82px auto 32px;
+ margin: 150px auto 32px;
padding: 0 16px;
max-width: 960px;
flex-direction: column;
@@ -60,7 +60,6 @@ p {
input {
width: 400px;
- margin-top: 60px;
font-size: max(16px, 1em);
font-family: inherit;
padding: 0.25em 0.5em;
@@ -68,5 +67,19 @@ p {
border: 2px solid #eeeeee;
border-radius: 4px;
height: 28px;
+ margin-bottom: 15px;
+ }
+}
+
+::ng-deep {
+ .custom-class {
+ .popup-window {
+ padding: 0;
+
+ .heading {
+ color: #9c0404;
+ font-family: inherit;
+ }
+ }
}
}
diff --git a/projects/ng-password-validator-dev/src/app/app.component.ts b/projects/ng-password-validator-dev/src/app/app.component.ts
index 3dc8d45..e13c760 100644
--- a/projects/ng-password-validator-dev/src/app/app.component.ts
+++ b/projects/ng-password-validator-dev/src/app/app.component.ts
@@ -1,4 +1,5 @@
import { Component } from '@angular/core';
+import { NgPasswordValidatorOptions } from 'projects/ng-password-validator/src/lib/ng-password-validator.interface';
@Component({
selector: 'app-root',
@@ -7,8 +8,10 @@ import { Component } from '@angular/core';
})
export class AppComponent {
title = 'ng-password-validator-dev';
- options = {
+ options: NgPasswordValidatorOptions = {
placement: 'bottom',
+ type: 'inline',
+ 'custom-class': 'custom-class',
rules: {
password: {
type: 'range',
@@ -19,4 +22,8 @@ export class AppComponent {
shadow: true,
offset: 15,
};
+
+ isValid(event: boolean): void {
+ console.log(event);
+ }
}
diff --git a/projects/ng-password-validator/src/lib/ng-password-validator.component.scss b/projects/ng-password-validator/src/lib/ng-password-validator.component.scss
index a197259..03fe02d 100644
--- a/projects/ng-password-validator/src/lib/ng-password-validator.component.scss
+++ b/projects/ng-password-validator/src/lib/ng-password-validator.component.scss
@@ -32,7 +32,6 @@
.popup-window {
.heading {
font-size: $heading-font-size;
- color: $black;
margin-bottom: 0.5rem;
font-weight: 700;
}
@@ -97,6 +96,4 @@
}
}
}
-
-
}
diff --git a/projects/ng-password-validator/src/lib/ng-password-validator.component.ts b/projects/ng-password-validator/src/lib/ng-password-validator.component.ts
index 5a59f42..c520c93 100644
--- a/projects/ng-password-validator/src/lib/ng-password-validator.component.ts
+++ b/projects/ng-password-validator/src/lib/ng-password-validator.component.ts
@@ -324,8 +324,9 @@ export class NgPasswordValidatorComponent implements OnInit, OnChanges {
setStyles(): void {
this.setZIndex();
this.setAnimationDuration();
-
- this.hostClassShadow = this.options['shadow'];
+ if (this.options.type !== 'inline') {
+ this.hostClassShadow = this.options['shadow'];
+ }
this.hostStyleMaxWidth = this.options['max-width'] + 'px';
this.hostStyleWidth = this.options['width']
? this.options['width'] + 'px'
diff --git a/projects/ng-password-validator/src/lib/ng-password-validator.directive.ts b/projects/ng-password-validator/src/lib/ng-password-validator.directive.ts
index 9040b03..a171803 100644
--- a/projects/ng-password-validator/src/lib/ng-password-validator.directive.ts
+++ b/projects/ng-password-validator/src/lib/ng-password-validator.directive.ts
@@ -20,19 +20,14 @@ import { Subscription } from 'rxjs';
import { DataService } from './data.service';
import { NgPasswordValidatorComponent } from './ng-password-validator.component';
import {
+ HostComponent,
IElementPosition,
IPosition,
NgPasswordValidatorOptions,
} from './ng-password-validator.interface';
import { NgPasswordValidatorService } from './ng-password-validator.service';
import { defaultOptions } from './options';
-
-export interface HostComponent {
- data: any;
- show: boolean;
- close: boolean;
- events: any;
-}
+import { UtilsService } from './utils.service';
@Directive({
selector: '[NgPasswordValidator]',
@@ -52,25 +47,7 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
passwordOptions: NgPasswordValidatorOptions;
componentSubscribe: Subscription;
- @Input('options') set optionsInput(value: NgPasswordValidatorOptions) {
- if (value && defaultOptions) {
- this.passwordOptions = this.deepMerge(defaultOptions, value);
- this.createPasswordRegex();
- }
- }
@Input('NgPasswordValidator') popup: NgPasswordValidatorOptions;
- @Input('placement') placement: string;
- @Input('z-index') zIndex: number;
- @Input('animation-duration') animationDuration: number;
- @Input('custom-class') customClass: string;
- @Input('shadow') shadow: boolean;
- @Input('theme') theme: 'basic' | 'pro';
- @Input('offset') offset: number;
- @Input('width') width: number;
- @Input('max-width') maxWidth: number;
- @Input('position') position: IPosition;
- @Input('heading') heading: string;
- @Input('successMessage') successMessage: string;
@Output() events: EventEmitter = new EventEmitter();
@Output() valid: EventEmitter = new EventEmitter();
@@ -81,6 +58,7 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
private componentFactoryResolver: ComponentFactoryResolver,
private appRef: ApplicationRef,
private dataService: DataService,
+ private utilsService: UtilsService,
private injector: Injector
) {}
@@ -92,13 +70,6 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
return this.componentRef && this.componentRef.hostView.destroyed;
}
- /**
- * Get popup position
- *
- * @readonly
- * @type {(IElementPosition | IPosition)}
- * @memberof NgPasswordValidatorDirective
- */
get popupPosition(): IElementPosition | IPosition {
if (this.options['position']) {
return this.options['position'];
@@ -118,19 +89,6 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
this.show();
this.checkPassword(value);
}
- /**
- * Update password options
- *
- * @memberof NgPasswordValidatorDirective
- */
- updatePasswordOptions(): void {
- if (this.popup && defaultOptions) {
- this.passwordOptions = this.deepMerge(defaultOptions, this.popup);
- } else {
- this.passwordOptions = { ...defaultOptions };
- }
- this.createPasswordRegex();
- }
/**
* Focus out of input field
@@ -139,7 +97,10 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
*/
@HostListener('focusout')
onMouseLeave(): void {
- this.destroyPopup();
+ // If the template type is inline, don't destroy the created template
+ if (this.passwordOptions.type !== 'inline') {
+ this.destroyPopup();
+ }
this.valid.emit(this.isValid);
}
@@ -161,6 +122,12 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
* @memberof NgPasswordValidatorDirective
*/
ngOnChanges(changes: { popup: SimpleChange }): void {
+ // If the template type is 'inline' create the inline template directly
+ const templateType = changes.popup.currentValue.type;
+ if (templateType === 'inline') {
+ this.updatePasswordOptions();
+ this.show();
+ }
const changedOptions = this.getProperties(changes);
this.applyOptionsDefault(changedOptions, defaultOptions);
}
@@ -177,31 +144,6 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
}
}
- /**
- * Deep merge objects
- *
- * @param {NgPasswordValidatorOptions} target
- * @param {NgPasswordValidatorOptions} source
- * @returns {NgPasswordValidatorOptions}
- * @memberof NgPasswordValidatorDirective
- */
- deepMerge(
- target: NgPasswordValidatorOptions,
- source: NgPasswordValidatorOptions
- ): NgPasswordValidatorOptions {
- // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
- for (const key of Object.keys(source)) {
- if (source[key] instanceof Object) {
- Object.assign(source[key], this.deepMerge(target[key], source[key]));
- }
- }
-
- // Join `target` and modified `source`
- Object.assign(target || {}, source);
-
- return target;
- }
-
/**
* Create password regex
*
@@ -273,6 +215,23 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
this.dataService.updateValue(data);
}
+ /**
+ * Update password options
+ *
+ * @memberof NgPasswordValidatorDirective
+ */
+ updatePasswordOptions(): void {
+ if (this.popup && defaultOptions) {
+ this.passwordOptions = this.utilsService.deepMerge(
+ defaultOptions,
+ this.popup
+ );
+ } else {
+ this.passwordOptions = { ...defaultOptions };
+ }
+ this.createPasswordRegex();
+ }
+
/**
* Get properties
*
@@ -400,6 +359,11 @@ export class NgPasswordValidatorDirective implements OnDestroy, OnChanges {
).events.subscribe((event: any) => {
this.handleEvents(event);
});
+
+ if (this.options.type === 'inline') {
+ this.elementRef.nativeElement.style.marginBottom =
+ this.popupPosition['bottom'] + 'px';
+ }
}
/**
diff --git a/projects/ng-password-validator/src/lib/ng-password-validator.interface.ts b/projects/ng-password-validator/src/lib/ng-password-validator.interface.ts
index 8d8db7a..863e5f7 100644
--- a/projects/ng-password-validator/src/lib/ng-password-validator.interface.ts
+++ b/projects/ng-password-validator/src/lib/ng-password-validator.interface.ts
@@ -5,6 +5,7 @@ export interface NgPasswordValidatorOptions {
'custom-class'?: string;
shadow?: boolean;
theme?: 'basic' | 'pro';
+ type?: 'inline' | 'popup';
offset?: number;
width?: number;
'max-width'?: number;
@@ -48,3 +49,9 @@ export interface IStatus {
'include-lowercase-characters': boolean;
'include-uppercase-characters': boolean;
}
+export interface HostComponent {
+ data: any;
+ show: boolean;
+ close: boolean;
+ events: any;
+}
diff --git a/projects/ng-password-validator/src/lib/ng-password-validator.module.ts b/projects/ng-password-validator/src/lib/ng-password-validator.module.ts
index 76a8ba8..fddadf0 100644
--- a/projects/ng-password-validator/src/lib/ng-password-validator.module.ts
+++ b/projects/ng-password-validator/src/lib/ng-password-validator.module.ts
@@ -5,11 +5,12 @@ import { NgPasswordValidatorComponent } from './ng-password-validator.component'
import { NgPasswordValidatorDirective } from './ng-password-validator.directive';
import { NgPasswordValidatorOptions } from './ng-password-validator.interface';
import { NgPasswordValidatorService } from './ng-password-validator.service';
+import { UtilsService } from './utils.service';
@NgModule({
declarations: [NgPasswordValidatorDirective, NgPasswordValidatorComponent],
imports: [CommonModule],
- providers: [DataService],
+ providers: [DataService, UtilsService],
exports: [NgPasswordValidatorDirective],
entryComponents: [NgPasswordValidatorComponent],
})
diff --git a/projects/ng-password-validator/src/lib/options.ts b/projects/ng-password-validator/src/lib/options.ts
index 3eb3da9..d1156f0 100644
--- a/projects/ng-password-validator/src/lib/options.ts
+++ b/projects/ng-password-validator/src/lib/options.ts
@@ -9,6 +9,7 @@ export const defaultOptions: NgPasswordValidatorOptions = {
'custom-class': '',
shadow: true,
theme: 'pro',
+ type: 'popup',
offset: 8,
heading: 'Password Policy',
successMessage: 'Awesome! Password requirement fulfilled.',
diff --git a/projects/ng-password-validator/src/lib/utils.service.ts b/projects/ng-password-validator/src/lib/utils.service.ts
new file mode 100644
index 0000000..622ce7e
--- /dev/null
+++ b/projects/ng-password-validator/src/lib/utils.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { NgPasswordValidatorOptions } from './ng-password-validator.interface';
+
+@Injectable()
+export class UtilsService {
+ /**
+ * Deep merge objects
+ *
+ * @param {NgPasswordValidatorOptions} target
+ * @param {NgPasswordValidatorOptions} source
+ * @returns {NgPasswordValidatorOptions}
+ * @memberof UtilsService
+ */
+ deepMerge(
+ target: NgPasswordValidatorOptions,
+ source: NgPasswordValidatorOptions
+ ): NgPasswordValidatorOptions {
+ // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
+ for (const key of Object.keys(source)) {
+ if (source[key] instanceof Object) {
+ Object.assign(source[key], this.deepMerge(target[key], source[key]));
+ }
+ }
+
+ // Join `target` and modified `source`
+ Object.assign(target || {}, source);
+
+ return target;
+ }
+}