import {
Component, Input, forwardRef, SimpleChanges, ViewChild, OnChanges, Output, EventEmitter,
ElementRef
} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import {
ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, Validator,
AbstractControl, ValidationErrors
} from '@angular/forms';
import {
inRangeValidator, greaterOrEqualValidator, lessOrEqualValidator,
greaterThanValidator, lessThanValidator, equalValidator, lengthValidator, floatValidator, integerValidator
} from './validators';
import {isNullOrUndefined} from "util";
const noop = () => {
};
export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => WfmTextInputComponent),
multi: true
};
export const CUSTOM_INPUT_VALIDATOR: any = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => WfmTextInputComponent),
multi: true
};
@Component({
selector: 'wfm-text-input',
template: `
{{hintLabel}}
{{ 'VALIDATE.REQUIRED' | translate }}
{{ 'VALIDATE.MAX_LENGTH' | translate: {value: maxlength} }}
{{ 'VALIDATE.MIN_LENGTH' | translate: {value: minlength} }}
{{ 'VALIDATE.LENGTH' | translate: {value: length} }}
{{ patternError }}
{{ getCommonRuleMessage(minlength + '-' + maxlength) }}
{{ 'VALIDATE.GREATER_OR_EQUAL' | translate: {value: greater_or_equal} }}
{{ 'VALIDATE.LESS_OR_EQUAL' | translate: {value: less_or_equal} }}
{{ 'VALIDATE.GREATER_THAN' | translate: {value: greater_than} }}
{{ 'VALIDATE.LESS_THAN' | translate: {value: less_than} }}
{{ 'VALIDATE.IN_RANGE' | translate: {value: in_range} }}
{{ 'VALIDATE.EQUAL' | translate: {value: equal} }}
{{ 'VALIDATE.FLOAT' | translate }}
{{ 'VALIDATE.INTEGER' | translate }}
`,
styles: [`
.hint-label {
color:#7c868d;
}
input.ng-invalid {
border-color: #d9534f;
}
`],
providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR, CUSTOM_INPUT_VALIDATOR]
})
export class WfmTextInputComponent implements ControlValueAccessor, Validator, OnChanges {
@Input() public disabled: boolean;
@Input() public inputType = 'string';
@Input() public inputClass = 'form-control';
@Input() public placeholder = '';
@Input() public hintLabel: string;
@Input() public patternError: string;
@Input() public required = false;
@Input() public maxlength: number;
@Input() public minlength: number;
@Input() public pattern = '';
@Input() public greater_or_equal: string; // >=
@Input() public less_or_equal: string; // <=
@Input() public greater_than: string; // >
@Input() public less_than: string; // <
@Input() public length: number;
@Input() public equal: any;
@Input() public in_range: string;
@Input() public isFocus: boolean;
@Output() public blur: any = new EventEmitter();
@Output() public click: any = new EventEmitter();
@ViewChild('wfInput') public wfInput: any;
public isHintLabelShow = false;
private innerValue: any = '';
private onTouchedCallback: () => void = noop;
private onChangeCallback: (_: any) => void = noop;
private _validators: any = {};
public generalRules = '^(?![-_.])(?!\\d*$)[\\da-zA-Z-_.]*$';
constructor(public translate: TranslateService,
private elementRef: ElementRef) {
}
public ngOnChanges(changes: SimpleChanges): void {
this._createValidator(changes);
if (this.isFocus) {
this.elementRef.nativeElement.querySelector('input').focus();
}
}
// 动态创建Validator
private _createValidator(changes: SimpleChanges): void {
for (let change in changes) {
switch (change) {
case 'in_range':
if (!isNullOrUndefined(this.in_range)) {
this._validators.in_range = inRangeValidator(JSON.parse(this.in_range));
}
break;
case 'greater_or_equal':
if (!isNullOrUndefined(this.greater_or_equal)) {
this._validators.greater_or_equal = greaterOrEqualValidator(this.greater_or_equal);
}
break;
case 'less_or_equal':
if (!isNullOrUndefined(this.less_or_equal)) {
this._validators.less_or_equal = lessOrEqualValidator(this.less_or_equal);
}
break;
case 'greater_than':
if (!isNullOrUndefined(this.greater_than)) {
this._validators.greater_than = greaterThanValidator(this.greater_than);
}
break;
case 'less_than':
if (!isNullOrUndefined(this.less_than)) {
this._validators.less_than = lessThanValidator(this.less_than);
}
break;
case 'equal':
if (!isNullOrUndefined(this.equal)) {
this._validators.equal = equalValidator(this.equal);
}
break;
case 'length':
if (!isNullOrUndefined(this.length)) {
this._validators.length = lengthValidator(this.length);
}
break;
case 'inputType':
delete this._validators.float;
delete this._validators.integer;
if (this.inputType === 'float') {
this._validators.float = floatValidator();
} else if (this.inputType === 'integer') {
this._validators.integer = integerValidator();
}
break;
}
}
}
// 执行控件验证
public validate(c: AbstractControl): ValidationErrors | null {
let errors: any;
for (let validatorName in this._validators) {
let validator = this._validators[validatorName];
if (validator) {
let errors = validator(c);
if (errors) {
return errors;
}
}
}
return null;
}
public onFocus(): void {
if (this.isFocus) {
this.click.emit();
}
this.isHintLabelShow = true;
}
public onBlur(): void {
this.blur.emit();
this.isHintLabelShow = false;
this.onTouchedCallback();
}
get value(): any {
this.validate(this.wfInput.control);
return this.innerValue;
};
set value(value: any) {
if (value !== this.innerValue) {
this.innerValue = value;
this.onChangeCallback(value);
}
}
writeValue(value: any) {
if (value !== this.innerValue) {
this.innerValue = value;
}
}
registerOnChange(fn: any) {
this.onChangeCallback = fn;
}
registerOnTouched(fn: any) {
this.onTouchedCallback = fn;
}
public getCommonRuleMessage(length: any): string {
let message = this.translate.get('VALIDATE.FIRST_CHARACTER')['value'] + ', ' +
this.translate.get('VALIDATE.NOT_ALL_NUMBER')['value'] + ', ' +
this.translate.get('VALIDATE.CHARACTER_LIMIT', {value: '[0-9],[a-z],[A-Z],[_],[-],[.]'})['value'] + ', ' +
this.translate.get('VALIDATE.CHARACTER_LENGTH', {value: length})['value'];
return message;
}
}