UNPKG

angular-jsf-components

Version:
201 lines (168 loc) 5.61 kB
import {ContentChildren, ElementRef, EventEmitter, Input, Output, QueryList,} from '@angular/core'; import {ControlValueAccessor, NgModel} from '@angular/forms'; import {isNull, isUndefined} from 'lodash'; import {FValidateRegexComponent} from '../components/f-validate-regex/f-validate-regex.component'; import {ValidationResponse} from '../objects/validation-response'; import {HFormService} from '../services/h-form.service'; import {MessageService} from '../services/message.service'; import {JsfOutput} from './jsf-output'; export abstract class JsfInput extends JsfOutput implements ControlValueAccessor { @Input() validatorMessage: string; @Input() converterMessage: string; @Input() requiredMessage: string; @Input() required: boolean; @Input() disabled: boolean; @Input() maxLength: number; @Input() validator: (elem: JsfInput) => Promise<ValidationResponse>; @Output() onchange = new EventEmitter<any>(); protected abstract model: NgModel; @ContentChildren(FValidateRegexComponent) private regexValidators: QueryList<FValidateRegexComponent>; private changeListener = []; private touchListener = []; private converterError = false; constructor(hFromService: HFormService, private messageService: MessageService, elementRef: ElementRef) { super(hFromService, elementRef); } // same as in JsfOutput but for some reason angular won't use the getter get value(): any { if (this.converter && this.innerValue) { return this.converter.transform(this.innerValue); } return this.innerValue; } set value(value: any) { if (this.innerValue !== value) { // converter given? then convert if (this.converter) { try { this.innerValue = this.converter.transformToObject(value); this.converterError = false; } catch (e) { // we have to save the value anyway, otherwise the input of the user is deleted this.innerValue = value; this.converterError = true; } } else { this.innerValue = value; } this.changeListener.forEach(f => f(this.innerValue)); } } async jsfOnRender(): Promise<void> { try { await super.jsfOnRender(); await this.validate(); } catch (e) { console.error(e); } } /** * * add more events if required * don't forget to use them in the actual .html File * */ async callAjax(event: string): Promise<void> { for (const ajax of this.ajax.toArray()) { if (ajax.event === event) { // if input is invalid and ajax is not set to immediate exec // prevent call let valid = true; if (!ajax.immediate) { valid = await this.validate(); } if (valid) { ajax.call(this); } } } } async onBlur() { try { await this.validate(); await this.callAjax('blur'); } catch (e) { console.error(e); } } async onChange() { this.onchange.emit(this.innerValue); try { await this.callAjax('change'); } catch (e) { console.error(e); } } /** * * @returns {Promise<boolean>} true when input ok */ async validate(): Promise<boolean> { let valid = true; let message = ''; // check for converter error if (this.converterError) { valid = false; message = this.converterMessage; } // check for regex validators for (const validator of this.regexValidators.toArray()) { if (!validator.validate(this.innerValue)) { valid = false; message = this.validatorMessage; } } // check for required if ((isNull(this.innerValue) || isUndefined(this.innerValue) || this.innerValue === '') && this.required && valid) { valid = false; message = this.requiredMessage; } // check for additional custom validators if (valid && this.validator) { const result = await this.validator(this); if (result.error) { valid = false; message = result.message; } } if (valid && this.maxLength && typeof this.innerValue === 'string' && this.innerValue.length > this.maxLength) { valid = false; message = `Input is too long. Maximum ${this.maxLength} characters allowed`; } if (valid) { const result = await this.triggerEvent('postValidate'); valid = !result.error; message = result.message; } this.messageService.submitError(this.simpleId, !valid, message); return valid; } /** * ng specific input functions */ touch() { this.touchListener.forEach(f => f()); } writeValue(value: any) { this.innerValue = value; } registerOnChange(fn: (value: any) => void) { this.changeListener.push(fn); } registerOnTouched(fn: () => void) { this.touchListener.push(fn); } }