Headless CMS and Content Managment Hub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

157 lines
4.7 KiB

/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights r vbeserved
*/
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Host, Input, OnChanges, OnDestroy, Optional } from '@angular/core';
import { AbstractControl, FormGroupDirective } from '@angular/forms';
import { Observable, Subscription } from 'rxjs';
import { fadeAnimation } from './animations';
const DEFAULT_ERRORS: { [key: string]: string } = {
required: '{field} is required.',
pattern: '{field} does not follow the pattern.',
patternmessage: '{message}',
minvalue: '{field} must be larger than {minValue}.',
maxvalue: '{field} must be smaller than {maxValue}.',
minmax: '{field} must have a length of more than {requiredLength}.',
maxlength: '{field} must have a length of less than {requiredLength}.',
match: '{message}',
validdatetime: '{field} is not a valid date time',
validnumber: '{field} is not a valid number.',
validvalues: '{field} is not a valid value.'
};
@Component({
selector: 'sqx-control-errors',
styleUrls: ['./control-errors.component.scss'],
templateUrl: './control-errors.component.html',
animations: [
fadeAnimation
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ControlErrorsComponent implements OnChanges, OnDestroy {
private displayFieldName: string;
private control: AbstractControl;
private controlSubscription: Subscription | null = null;
private originalMarkAsTouched: any;
@Input()
public for: string | AbstractControl;
@Input()
public fieldName: string;
@Input()
public errors: string;
@Input()
public submitted: boolean;
@Input()
public submitOnly = false;
public errorMessages: string[] = [];
constructor(
@Optional() @Host() private readonly formGroupDirective: FormGroupDirective,
private readonly changeDetector: ChangeDetectorRef
) {
}
public ngOnDestroy() {
this.unsubscribe();
}
public ngOnChanges() {
if (this.fieldName) {
this.displayFieldName = this.fieldName;
} else if (this.for) {
if (this.for instanceof String) {
this.displayFieldName = this.for.substr(0, 1).toUpperCase() + this.for.substr(1);
} else {
this.displayFieldName = 'field';
}
}
let control: AbstractControl | null = null;
if (typeof this.for === 'string') {
control = this.formGroupDirective.form.controls[this.for];
} else {
control = this.for;
}
if (this.control !== control) {
this.unsubscribe();
this.control = control;
if (control) {
this.controlSubscription =
Observable.merge(control.valueChanges, control.statusChanges)
.subscribe(() => {
this.createMessages();
});
this.originalMarkAsTouched = this.control.markAsTouched;
const self = this;
this.control['markAsTouched'] = function () {
self.originalMarkAsTouched.apply(this, arguments);
self.createMessages();
};
}
}
this.createMessages();
}
private unsubscribe() {
if (this.controlSubscription) {
this.controlSubscription.unsubscribe();
}
if (this.control && this.originalMarkAsTouched) {
this.control['markAsTouched'] = this.originalMarkAsTouched;
}
}
private createMessages() {
const errors: string[] = [];
if (this.control && this.control.invalid && ((this.control.touched && !this.submitOnly) || this.submitted) && this.control.errors) {
for (let key in <any>this.control.errors) {
if (this.control.errors.hasOwnProperty(key)) {
let message = (this.errors ? this.errors[key] : null) || DEFAULT_ERRORS[key.toLowerCase()];
if (!message) {
continue;
}
const properties = this.control.errors[key];
for (let property in properties) {
if (properties.hasOwnProperty(property)) {
message = message.replace(`{${property}}`, properties[property]);
}
}
message = message.replace('{field}', this.displayFieldName);
errors.push(message);
}
}
}
this.errorMessages = errors;
this.changeDetector.detectChanges();
}
}