123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- 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, Subscription } from 'rxjs';
- import { debounceTime } from 'rxjs/operators';
- export abstract class NativeInputComponent implements OnInit, OnDestroy {
- @Input()
- control: FormControl;
- @Input()
- set meta(meta: StringMap<any>) {
- this._meta = meta;
- this.exposeForTemplate();
- }
- @Output()
- call: EventEmitter<string> = new EventEmitter<string>();
- readonly componentName: string;
- exposeMetaInTemplate: string[] = [];
- _meta: StringMap<any>;
- pendingValidation: boolean;
- hasFocus: boolean = false;
- waitForFirstChange: boolean = false;
- keyUp$: 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,
- protected _cdr: ChangeDetectorRef
- ) {}
- ngOnInit() {
- // 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.valueSBX = this.control.valueChanges.subscribe(val => {
- if (val === null) {
- this.control.setValue(this._meta.default); // Reset to default value (as opposed to null) after an Angular FormGroup.reset()
- return;
- }
- this.markForCheck();
- });
- this.statusSBX = this.control.statusChanges.subscribe(status => {
- if (status === 'PENDING') {
- this.pendingValidation = true;
- } else if (this.pendingValidation) {
- this.pendingValidation = false;
- this.markForCheck();
- }
- });
- }
- 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() {
- // Move meta variables up a level, for direct access in templates
- this.exposeMetaInTemplate.map(p => this[p] = this._meta[p] !== undefined ? this._meta[p] : this[p]);
- }
- markForCheck() {
- if (this._cdr) {
- this._cdr.markForCheck();
- }
- }
- handle(fnId: string, val: any): void {
- this.call.emit(fnId); // Add control's current value
- }
- handleChange(): void {
- if (this._meta.change) {
- this.handle(this._meta.change, this.control.value);
- }
- }
- getName(): string {
- return this.componentName;
- }
- getFirstFailureMsg(): string {
- if (!this.control.errors || this.control.errors === {}) {
- return '';
- }
- const key = Object.keys(this.control.errors)[0];
- return this._meta.valFailureMsgs[key] || this.valErrsService.getFriendly(key, this.control.errors[key]);
- }
- 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;
- }
- }
- }
|