|
@@ -1,9 +1,10 @@
|
|
|
-import { OnInit, Input, Output, ChangeDetectorRef, EventEmitter } from '@angular/core';
|
|
|
+import { OnInit, OnDestroy, Input, Output, ChangeDetectorRef, EventEmitter } from '@angular/core';
|
|
|
import { FormControl } from '@angular/forms';
|
|
|
import { FriendlyValidationErrorsService } from './../../services/friendly-validation-errors.service';
|
|
|
-// import { Subject } from 'rxjs';
|
|
|
+import { Subject, Subscription } from 'rxjs';
|
|
|
+import { debounceTime } from 'rxjs/operators';
|
|
|
|
|
|
-export abstract class NativeInputComponent implements OnInit {
|
|
|
+export abstract class NativeInputComponent implements OnInit, OnDestroy {
|
|
|
|
|
|
@Input()
|
|
|
control: FormControl;
|
|
@@ -22,8 +23,15 @@ export abstract class NativeInputComponent implements OnInit {
|
|
|
_meta: StringMap<any>;
|
|
|
|
|
|
pendingValidation: boolean;
|
|
|
+ hasFocus: boolean = false;
|
|
|
+ waitForFirstChange: boolean = false;
|
|
|
+ keyUp$: Subject<string> = new Subject();
|
|
|
|
|
|
- // firstFailureMsg: Subject<string> = new Subject();
|
|
|
+ valueSBX: Subscription;
|
|
|
+ statusSBX: Subscription;
|
|
|
+ keyUpSBX: Subscription;
|
|
|
+
|
|
|
+ keyUpValidationDelay: number = 2000; // Validate after 2 seconds IF the control still has focus
|
|
|
|
|
|
constructor(
|
|
|
protected valErrsService: FriendlyValidationErrorsService,
|
|
@@ -34,8 +42,8 @@ export abstract class NativeInputComponent implements OnInit {
|
|
|
// this.control is not an instance of FormControl when it's a Checkbutton in a Checkbutton group (but is when it's a solo Checkbutton) - BUT WHY? WHY!!!
|
|
|
// Hence the 'if' statement
|
|
|
if (this.control instanceof FormControl) {
|
|
|
- this.control.valueChanges.subscribe(this.markForCheck.bind(this));
|
|
|
- this.control.statusChanges.subscribe(status => {
|
|
|
+ this.valueSBX = this.control.valueChanges.subscribe(this.markForCheck.bind(this));
|
|
|
+ this.statusSBX = this.control.statusChanges.subscribe(status => {
|
|
|
if (status === 'PENDING') {
|
|
|
this.pendingValidation = true;
|
|
|
} else if (this.pendingValidation) {
|
|
@@ -44,6 +52,27 @@ export abstract class NativeInputComponent implements OnInit {
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
+ this.keyUpSBX = this.keyUp$.pipe(debounceTime(this.keyUpValidationDelay)).subscribe(val => {
|
|
|
+ if (this.hasFocus) {
|
|
|
+ // THE ORDER OF THE NEXT THREE LINES IS IMPORTANT!
|
|
|
+ // We MUST make the control as dirty before setting the value to avoid corrupting the initialValue recorded in Dynaform's makeAsyncTest utility
|
|
|
+ this.control.markAsTouched();
|
|
|
+ this.control.markAsDirty();
|
|
|
+ this.control.setValue(val);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ ngOnDestroy() {
|
|
|
+ if (this.valueSBX) {
|
|
|
+ this.valueSBX.unsubscribe();
|
|
|
+ }
|
|
|
+ if (this.statusSBX) {
|
|
|
+ this.statusSBX.unsubscribe();
|
|
|
+ }
|
|
|
+ if (this.keyUpSBX) {
|
|
|
+ this.keyUpSBX.unsubscribe();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
exposeForTemplate() {
|
|
@@ -79,17 +108,23 @@ export abstract class NativeInputComponent implements OnInit {
|
|
|
return this._meta.valFailureMsgs[key] || this.valErrsService.getFriendly(key, this.control.errors[key]);
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- getFirstFailureMsg(): void {
|
|
|
- if (!this.control.errors || this.control.errors === {}) {
|
|
|
- this.firstFailureMsg.next('');
|
|
|
- }
|
|
|
- console.log(this.control.errors);
|
|
|
- const key = Object.keys(this.control.errors)[0];
|
|
|
- const err = this._meta.valFailureMsgs[key] || this.valErrsService.getFriendly(key, this.control.errors[key]);
|
|
|
- this.firstFailureMsg.next(err);
|
|
|
+ gainFocus(): void {
|
|
|
+ this.hasFocus = true;
|
|
|
+ this.waitForFirstChange = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ loseFocus(): void {
|
|
|
+ this.hasFocus = false;
|
|
|
}
|
|
|
- */
|
|
|
|
|
|
+ handleKeyup(currentFieldValue: string): void {
|
|
|
+ this.keyUp$.next(currentFieldValue);
|
|
|
+ if (this.control.value && this.waitForFirstChange) {
|
|
|
+ // Hide any validation errors if the control has a previous value (set after Angular's first updateOn event) and its value has changed
|
|
|
+ // NOTE that this.control.value may lag behind currentFieldValue depending on the updateOn startegy chosen
|
|
|
+ this.control.markAsPending();
|
|
|
+ this.waitForFirstChange = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
}
|