f70a2b9b7c49ef7e013bfd02bacbd54d97cc9484
[sdc/sdc-workflow-designer.git] /
1 import {
2     Component, Input, forwardRef, SimpleChanges, ViewChild, OnChanges, Output, EventEmitter,
3     ElementRef
4 } from '@angular/core';
5 import {TranslateService} from '@ngx-translate/core';
6 import {
7     ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, Validator,
8     AbstractControl, ValidationErrors
9 } from '@angular/forms';
10 import {
11     inRangeValidator, greaterOrEqualValidator, lessOrEqualValidator,
12     greaterThanValidator, lessThanValidator, equalValidator, lengthValidator, floatValidator, integerValidator
13 } from './validators';
14 import {isNullOrUndefined} from "util";
15
16 const noop = () => {
17 };
18
19 export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
20     provide: NG_VALUE_ACCESSOR,
21     useExisting: forwardRef(() => WfmTextInputComponent),
22     multi: true
23 };
24
25 export const CUSTOM_INPUT_VALIDATOR: any = {
26     provide: NG_VALIDATORS,
27     useExisting: forwardRef(() => WfmTextInputComponent),
28     multi: true
29 };
30
31 @Component({
32     selector: 'wfm-text-input',
33     template: `
34         <input type="text"
35             [disabled]="disabled" 
36             [class]="inputClass"
37             [placeholder]="placeholder"
38             [required]="required"
39             [maxlength]="maxlength"
40             [minlength]="minlength"
41             [pattern]="pattern"
42             (focus)="onFocus()"
43             (blur)="onBlur()"
44             [(ngModel)]="value"
45             [ngModelOptions]="{standalone: true}"
46             #wfInput="ngModel"
47         />
48
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 }}
52         </small>
53         <small [hidden]="!wfInput.errors?.maxlength" class="text-danger">
54             {{ 'VALIDATE.MAX_LENGTH' | translate: {value: maxlength} }}
55         </small>
56         <small [hidden]="!wfInput.errors?.minlength" class="text-danger">
57             {{ 'VALIDATE.MIN_LENGTH' | translate: {value: minlength} }}
58         </small>
59         <small [hidden]="!wfInput.errors?.length" class="text-danger">
60             {{ 'VALIDATE.LENGTH' | translate: {value: length} }}
61         </small>
62         <small *ngIf="patternError" [hidden]="!wfInput.errors?.pattern" class="text-danger">
63             {{ patternError }}
64         </small>
65         <small *ngIf="!patternError && pattern === generalRules" [hidden]="!wfInput.errors?.pattern" class="text-danger">
66             {{ getCommonRuleMessage(minlength + '-' + maxlength) }}
67         </small>
68         <small [hidden]="!wfInput.errors?.greater_or_equal" class="text-danger">
69             {{ 'VALIDATE.GREATER_OR_EQUAL' | translate: {value: greater_or_equal} }}
70         </small>
71         <small [hidden]="!wfInput.errors?.less_or_equal" class="text-danger">
72             {{ 'VALIDATE.LESS_OR_EQUAL' | translate: {value: less_or_equal} }}
73         </small>
74         <small [hidden]="!wfInput.errors?.greater_than" class="text-danger">
75             {{ 'VALIDATE.GREATER_THAN' | translate: {value: greater_than} }}
76         </small>
77         <small [hidden]="!wfInput.errors?.less_than" class="text-danger">
78             {{ 'VALIDATE.LESS_THAN' | translate: {value: less_than} }}
79         </small>
80         <small [hidden]="!wfInput.errors?.in_range" class="text-danger">
81             {{ 'VALIDATE.IN_RANGE' | translate: {value: in_range} }}
82         </small>
83         <small [hidden]="!wfInput.errors?.equal" class="text-danger">
84             {{ 'VALIDATE.EQUAL' | translate: {value: equal} }}
85         </small>
86         <small [hidden]="!wfInput.errors?.float" class="text-danger">
87             {{ 'VALIDATE.FLOAT' | translate }}
88         </small>
89         <small [hidden]="!wfInput.errors?.integer" class="text-danger">
90             {{ 'VALIDATE.INTEGER' | translate }}
91         </small>
92     `,
93     styles: [`
94         .hint-label {
95             color:#7c868d;
96         }
97         input.ng-invalid {
98             border-color: #d9534f;
99         }
100     `],
101     providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR, CUSTOM_INPUT_VALIDATOR]
102 })
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;
125
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-_.]*$';
132
133     constructor(public translate: TranslateService,
134                 private elementRef: ElementRef) {
135
136     }
137
138     public ngOnChanges(changes: SimpleChanges): void {
139         this._createValidator(changes);
140         if (this.isFocus) {
141             this.elementRef.nativeElement.querySelector('input').focus();
142         }
143     }
144
145     // 动态创建Validator
146     private _createValidator(changes: SimpleChanges): void {
147         for (let change in changes) {
148             switch (change) {
149                 case 'in_range':
150                     if (!isNullOrUndefined(this.in_range)) {
151                         this._validators.in_range = inRangeValidator(JSON.parse(this.in_range));
152                     }
153                     break;
154                 case 'greater_or_equal':
155                     if (!isNullOrUndefined(this.greater_or_equal)) {
156                         this._validators.greater_or_equal = greaterOrEqualValidator(this.greater_or_equal);
157                     }
158                     break;
159                 case 'less_or_equal':
160                     if (!isNullOrUndefined(this.less_or_equal)) {
161                         this._validators.less_or_equal = lessOrEqualValidator(this.less_or_equal);
162                     }
163                     break;
164                 case 'greater_than':
165                     if (!isNullOrUndefined(this.greater_than)) {
166                         this._validators.greater_than = greaterThanValidator(this.greater_than);
167                     }
168                     break;
169                 case 'less_than':
170                     if (!isNullOrUndefined(this.less_than)) {
171                         this._validators.less_than = lessThanValidator(this.less_than);
172                     }
173                     break;
174                 case 'equal':
175                     if (!isNullOrUndefined(this.equal)) {
176                         this._validators.equal = equalValidator(this.equal);
177                     }
178                     break;
179                 case 'length':
180                     if (!isNullOrUndefined(this.length)) {
181                         this._validators.length = lengthValidator(this.length);
182                     }
183                     break;
184                 case 'inputType':
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();
191                     }
192                     break;
193             }
194         }
195     }
196
197     // 执行控件验证
198     public validate(c: AbstractControl): ValidationErrors | null {
199         let errors: any;
200         for (let validatorName in this._validators) {
201             let validator = this._validators[validatorName];
202             if (validator) {
203                 let errors = validator(c);
204                 if (errors) {
205                     return errors;
206                 }
207             }
208         }
209         return null;
210     }
211
212     public onFocus(): void {
213         if (this.isFocus) {
214             this.click.emit();
215         }
216         this.isHintLabelShow = true;
217     }
218
219     public onBlur(): void {
220         this.blur.emit();
221         this.isHintLabelShow = false;
222         this.onTouchedCallback();
223     }
224
225     get value(): any {
226         this.validate(this.wfInput.control);
227         return this.innerValue;
228     };
229
230     set value(value: any) {
231         if (value !== this.innerValue) {
232             this.innerValue = value;
233             this.onChangeCallback(value);
234         }
235     }
236
237     writeValue(value: any) {
238         if (value !== this.innerValue) {
239             this.innerValue = value;
240         }
241     }
242
243     registerOnChange(fn: any) {
244         this.onChangeCallback = fn;
245     }
246
247     registerOnTouched(fn: any) {
248         this.onTouchedCallback = fn;
249     }
250
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'];
256         return message;
257     }
258 }