2 Component, Input, forwardRef, SimpleChanges, ViewChild, OnChanges, Output, EventEmitter,
4 } from '@angular/core';
5 import {TranslateService} from '@ngx-translate/core';
7 ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, Validator,
8 AbstractControl, ValidationErrors
9 } from '@angular/forms';
11 inRangeValidator, greaterOrEqualValidator, lessOrEqualValidator,
12 greaterThanValidator, lessThanValidator, equalValidator, lengthValidator, floatValidator, integerValidator
13 } from './validators';
14 import {isNullOrUndefined} from "util";
19 export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
20 provide: NG_VALUE_ACCESSOR,
21 useExisting: forwardRef(() => WfmTextInputComponent),
25 export const CUSTOM_INPUT_VALIDATOR: any = {
26 provide: NG_VALIDATORS,
27 useExisting: forwardRef(() => WfmTextInputComponent),
32 selector: 'wfm-text-input',
37 [placeholder]="placeholder"
39 [maxlength]="maxlength"
40 [minlength]="minlength"
45 [ngModelOptions]="{standalone: true}"
49 <small [hidden]="!wfInput.valid || !hintLabel || !isHintLabelShow" class="hint-label">{{hintLabel}}</small>
50 <small [hidden]="!wfInput.errors?.required" class="text-danger">
51 {{ 'VALIDATE.REQUIRED' | translate }}
53 <small [hidden]="!wfInput.errors?.maxlength" class="text-danger">
54 {{ 'VALIDATE.MAX_LENGTH' | translate: {value: maxlength} }}
56 <small [hidden]="!wfInput.errors?.minlength" class="text-danger">
57 {{ 'VALIDATE.MIN_LENGTH' | translate: {value: minlength} }}
59 <small [hidden]="!wfInput.errors?.length" class="text-danger">
60 {{ 'VALIDATE.LENGTH' | translate: {value: length} }}
62 <small *ngIf="patternError" [hidden]="!wfInput.errors?.pattern" class="text-danger">
65 <small *ngIf="!patternError && pattern === generalRules" [hidden]="!wfInput.errors?.pattern" class="text-danger">
66 {{ getCommonRuleMessage(minlength + '-' + maxlength) }}
68 <small [hidden]="!wfInput.errors?.greater_or_equal" class="text-danger">
69 {{ 'VALIDATE.GREATER_OR_EQUAL' | translate: {value: greater_or_equal} }}
71 <small [hidden]="!wfInput.errors?.less_or_equal" class="text-danger">
72 {{ 'VALIDATE.LESS_OR_EQUAL' | translate: {value: less_or_equal} }}
74 <small [hidden]="!wfInput.errors?.greater_than" class="text-danger">
75 {{ 'VALIDATE.GREATER_THAN' | translate: {value: greater_than} }}
77 <small [hidden]="!wfInput.errors?.less_than" class="text-danger">
78 {{ 'VALIDATE.LESS_THAN' | translate: {value: less_than} }}
80 <small [hidden]="!wfInput.errors?.in_range" class="text-danger">
81 {{ 'VALIDATE.IN_RANGE' | translate: {value: in_range} }}
83 <small [hidden]="!wfInput.errors?.equal" class="text-danger">
84 {{ 'VALIDATE.EQUAL' | translate: {value: equal} }}
86 <small [hidden]="!wfInput.errors?.float" class="text-danger">
87 {{ 'VALIDATE.FLOAT' | translate }}
89 <small [hidden]="!wfInput.errors?.integer" class="text-danger">
90 {{ 'VALIDATE.INTEGER' | translate }}
98 border-color: #d9534f;
101 providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR, CUSTOM_INPUT_VALIDATOR]
103 export class WfmTextInputComponent implements ControlValueAccessor, Validator, OnChanges {
104 @Input() public disabled: boolean;
105 @Input() public inputType = 'string';
106 @Input() public inputClass = 'form-control';
107 @Input() public placeholder = '';
108 @Input() public hintLabel: string;
109 @Input() public patternError: string;
110 @Input() public required = false;
111 @Input() public maxlength: number;
112 @Input() public minlength: number;
113 @Input() public pattern = '';
114 @Input() public greater_or_equal: string; // >=
115 @Input() public less_or_equal: string; // <=
116 @Input() public greater_than: string; // >
117 @Input() public less_than: string; // <
118 @Input() public length: number;
119 @Input() public equal: any;
120 @Input() public in_range: string;
121 @Input() public isFocus: boolean;
122 @Output() public blur: any = new EventEmitter();
123 @Output() public click: any = new EventEmitter();
124 @ViewChild('wfInput') public wfInput: any;
126 public isHintLabelShow = false;
127 private innerValue: any = '';
128 private onTouchedCallback: () => void = noop;
129 private onChangeCallback: (_: any) => void = noop;
130 private _validators: any = {};
131 public generalRules = '^(?![-_.])(?!\\d*$)[\\da-zA-Z-_.]*$';
133 constructor(public translate: TranslateService,
134 private elementRef: ElementRef) {
138 public ngOnChanges(changes: SimpleChanges): void {
139 this._createValidator(changes);
141 this.elementRef.nativeElement.querySelector('input').focus();
146 private _createValidator(changes: SimpleChanges): void {
147 for (let change in changes) {
150 if (!isNullOrUndefined(this.in_range)) {
151 this._validators.in_range = inRangeValidator(JSON.parse(this.in_range));
154 case 'greater_or_equal':
155 if (!isNullOrUndefined(this.greater_or_equal)) {
156 this._validators.greater_or_equal = greaterOrEqualValidator(this.greater_or_equal);
159 case 'less_or_equal':
160 if (!isNullOrUndefined(this.less_or_equal)) {
161 this._validators.less_or_equal = lessOrEqualValidator(this.less_or_equal);
165 if (!isNullOrUndefined(this.greater_than)) {
166 this._validators.greater_than = greaterThanValidator(this.greater_than);
170 if (!isNullOrUndefined(this.less_than)) {
171 this._validators.less_than = lessThanValidator(this.less_than);
175 if (!isNullOrUndefined(this.equal)) {
176 this._validators.equal = equalValidator(this.equal);
180 if (!isNullOrUndefined(this.length)) {
181 this._validators.length = lengthValidator(this.length);
185 delete this._validators.float;
186 delete this._validators.integer;
187 if (this.inputType === 'float') {
188 this._validators.float = floatValidator();
189 } else if (this.inputType === 'integer') {
190 this._validators.integer = integerValidator();
198 public validate(c: AbstractControl): ValidationErrors | null {
200 for (let validatorName in this._validators) {
201 let validator = this._validators[validatorName];
203 let errors = validator(c);
212 public onFocus(): void {
216 this.isHintLabelShow = true;
219 public onBlur(): void {
221 this.isHintLabelShow = false;
222 this.onTouchedCallback();
226 this.validate(this.wfInput.control);
227 return this.innerValue;
230 set value(value: any) {
231 if (value !== this.innerValue) {
232 this.innerValue = value;
233 this.onChangeCallback(value);
237 writeValue(value: any) {
238 if (value !== this.innerValue) {
239 this.innerValue = value;
243 registerOnChange(fn: any) {
244 this.onChangeCallback = fn;
247 registerOnTouched(fn: any) {
248 this.onTouchedCallback = fn;
251 public getCommonRuleMessage(length: any): string {
252 let message = this.translate.get('VALIDATE.FIRST_CHARACTER')['value'] + ', ' +
253 this.translate.get('VALIDATE.NOT_ALL_NUMBER')['value'] + ', ' +
254 this.translate.get('VALIDATE.CHARACTER_LIMIT', {value: '[0-9],[a-z],[A-Z],[_],[-],[.]'})['value'] + ', ' +
255 this.translate.get('VALIDATE.CHARACTER_LENGTH', {value: length})['value'];