UI: Fix data keys chips validation.
This commit is contained in:
parent
7699e49655
commit
3ab6b0e2b7
@ -33,13 +33,13 @@ import {
|
|||||||
import {
|
import {
|
||||||
AbstractControl,
|
AbstractControl,
|
||||||
ControlValueAccessor,
|
ControlValueAccessor,
|
||||||
FormGroupDirective,
|
FormGroupDirective, NG_VALIDATORS,
|
||||||
NG_VALUE_ACCESSOR,
|
NG_VALUE_ACCESSOR,
|
||||||
NgForm,
|
NgForm,
|
||||||
UntypedFormBuilder,
|
UntypedFormBuilder,
|
||||||
UntypedFormControl,
|
UntypedFormControl,
|
||||||
UntypedFormGroup,
|
UntypedFormGroup,
|
||||||
ValidationErrors
|
ValidationErrors, Validator
|
||||||
} from '@angular/forms';
|
} from '@angular/forms';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { filter, map, mergeMap, publishReplay, refCount, share, tap } from 'rxjs/operators';
|
import { filter, map, mergeMap, publishReplay, refCount, share, tap } from 'rxjs/operators';
|
||||||
@ -62,7 +62,7 @@ import {
|
|||||||
DataKeyConfigDialogComponent,
|
DataKeyConfigDialogComponent,
|
||||||
DataKeyConfigDialogData
|
DataKeyConfigDialogData
|
||||||
} from '@home/components/widget/config/data-key-config-dialog.component';
|
} from '@home/components/widget/config/data-key-config-dialog.component';
|
||||||
import { deepClone, guid, isDefinedAndNotNull, isUndefined } from '@core/utils';
|
import { deepClone, guid, isDefinedAndNotNull, isObject, isUndefined } from '@core/utils';
|
||||||
import { Dashboard } from '@shared/models/dashboard.models';
|
import { Dashboard } from '@shared/models/dashboard.models';
|
||||||
import { AggregationType } from '@shared/models/time/time.models';
|
import { AggregationType } from '@shared/models/time/time.models';
|
||||||
import { DndDropEvent } from 'ngx-drag-drop/lib/dnd-dropzone.directive';
|
import { DndDropEvent } from 'ngx-drag-drop/lib/dnd-dropzone.directive';
|
||||||
@ -81,15 +81,20 @@ import { TbPopoverService } from '@shared/components/popover.service';
|
|||||||
provide: NG_VALUE_ACCESSOR,
|
provide: NG_VALUE_ACCESSOR,
|
||||||
useExisting: forwardRef(() => DataKeysComponent),
|
useExisting: forwardRef(() => DataKeysComponent),
|
||||||
multi: true
|
multi: true
|
||||||
} /*,
|
},
|
||||||
|
{
|
||||||
|
provide: NG_VALIDATORS,
|
||||||
|
useExisting: forwardRef(() => DataKeysComponent),
|
||||||
|
multi: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: ErrorStateMatcher,
|
provide: ErrorStateMatcher,
|
||||||
useExisting: DataKeysComponent
|
useExisting: DataKeysComponent
|
||||||
} */
|
}
|
||||||
],
|
],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChanges, ErrorStateMatcher {
|
export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChanges, ErrorStateMatcher, Validator {
|
||||||
|
|
||||||
public get hideDataKeyLabel(): boolean {
|
public get hideDataKeyLabel(): boolean {
|
||||||
return this.datasourceComponent.hideDataKeyLabel;
|
return this.datasourceComponent.hideDataKeyLabel;
|
||||||
@ -205,6 +210,9 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
|
|
||||||
private propagateChange = (v: any) => { };
|
private propagateChange = (v: any) => { };
|
||||||
|
|
||||||
|
private keysRequired = this._keysRequired.bind(this);
|
||||||
|
private keysValidator = this._keysValidator.bind(this);
|
||||||
|
|
||||||
constructor(private store: Store<AppState>,
|
constructor(private store: Store<AppState>,
|
||||||
@SkipSelf() private errorStateMatcher: ErrorStateMatcher,
|
@SkipSelf() private errorStateMatcher: ErrorStateMatcher,
|
||||||
private datasourceComponent: DatasourceComponent,
|
private datasourceComponent: DatasourceComponent,
|
||||||
@ -220,12 +228,16 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateValidators() {
|
updateValidators() {
|
||||||
this.keysListFormGroup.get('keys').setValidators(this.required ? [this.keysRequired] : []);
|
if (this.required) {
|
||||||
|
this.keysListFormGroup.get('keys').addValidators(this.keysRequired);
|
||||||
|
} else {
|
||||||
|
this.keysListFormGroup.get('keys').removeValidators(this.keysRequired);
|
||||||
|
}
|
||||||
this.keysListFormGroup.get('keys').updateValueAndValidity();
|
this.keysListFormGroup.get('keys').updateValueAndValidity();
|
||||||
}
|
}
|
||||||
|
|
||||||
keysRequired(control: AbstractControl): ValidationErrors | null {
|
private _keysRequired(control: AbstractControl): ValidationErrors | null {
|
||||||
const value = control.value;
|
const value = this.modelValue;
|
||||||
if (value && Array.isArray(value) && value.length) {
|
if (value && Array.isArray(value) && value.length) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
@ -233,8 +245,23 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _keysValidator(control: AbstractControl): ValidationErrors | null {
|
||||||
|
const value = this.modelValue;
|
||||||
|
if (value && Array.isArray(value)) {
|
||||||
|
if (value.some(v => isObject(v) && (!v.type || !v.name))) {
|
||||||
|
return {
|
||||||
|
dataKey: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
registerOnChange(fn: any): void {
|
registerOnChange(fn: any): void {
|
||||||
this.propagateChange = fn;
|
this.propagateChange = fn;
|
||||||
|
if (!this.keysListFormGroup.valid) {
|
||||||
|
this.propagateChange(this.modelValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registerOnTouched(fn: any): void {
|
registerOnTouched(fn: any): void {
|
||||||
@ -242,9 +269,12 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.keysListFormGroup = this.fb.group({
|
this.keysListFormGroup = this.fb.group({
|
||||||
keys: [null, this.required ? [this.keysRequired] : []],
|
keys: [null, [this.keysValidator]],
|
||||||
key: [null]
|
key: [null]
|
||||||
});
|
});
|
||||||
|
if (this.required) {
|
||||||
|
this.keysListFormGroup.get('keys').addValidators(this.keysRequired);
|
||||||
|
}
|
||||||
this.alarmKeys = [];
|
this.alarmKeys = [];
|
||||||
for (const name of Object.keys(alarmFields)) {
|
for (const name of Object.keys(alarmFields)) {
|
||||||
this.alarmKeys.push({
|
this.alarmKeys.push({
|
||||||
@ -335,8 +365,8 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
} else {
|
} else {
|
||||||
this.keys = [];
|
this.keys = [];
|
||||||
}
|
}
|
||||||
this.keysListFormGroup.get('keys').setValue(this.keys);
|
|
||||||
this.modelValue = this.keys.length ? [...this.keys] : null;
|
this.modelValue = this.keys.length ? [...this.keys] : null;
|
||||||
|
this.keysListFormGroup.get('keys').setValue(this.keys);
|
||||||
if (this.keyInput) {
|
if (this.keyInput) {
|
||||||
this.keyInput.nativeElement.value = '';
|
this.keyInput.nativeElement.value = '';
|
||||||
}
|
}
|
||||||
@ -374,7 +404,7 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
|
|
||||||
isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean {
|
isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean {
|
||||||
const originalErrorState = this.errorStateMatcher.isErrorState(control, form);
|
const originalErrorState = this.errorStateMatcher.isErrorState(control, form);
|
||||||
const customErrorState = this.required && (!this.modelValue || !this.modelValue.length);
|
const customErrorState = this.keysListFormGroup.get('keys').hasError('dataKey');
|
||||||
return originalErrorState || customErrorState;
|
return originalErrorState || customErrorState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,12 +425,20 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
this.keysListFormGroup.get('keys').setValue(this.keys);
|
this.keysListFormGroup.get('keys').setValue(this.keys);
|
||||||
} else {
|
} else {
|
||||||
this.keys = [];
|
this.keys = [];
|
||||||
this.keysListFormGroup.get('keys').setValue(this.keys);
|
|
||||||
this.modelValue = null;
|
this.modelValue = null;
|
||||||
|
this.keysListFormGroup.get('keys').setValue(this.keys);
|
||||||
}
|
}
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate(c: UntypedFormControl) {
|
||||||
|
return (this.keysListFormGroup.get('keys').hasError('dataKey')) ? {
|
||||||
|
dataKeys: {
|
||||||
|
valid: false,
|
||||||
|
},
|
||||||
|
} : null;
|
||||||
|
}
|
||||||
|
|
||||||
onFocus() {
|
onFocus() {
|
||||||
if (this.dirty) {
|
if (this.dirty) {
|
||||||
this.keysListFormGroup.get('key').updateValueAndValidity({onlySelf: true, emitEvent: true});
|
this.keysListFormGroup.get('key').updateValueAndValidity({onlySelf: true, emitEvent: true});
|
||||||
@ -441,8 +479,8 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
const index = this.keys.indexOf(key);
|
const index = this.keys.indexOf(key);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
this.keys.splice(index, 1);
|
this.keys.splice(index, 1);
|
||||||
this.keysListFormGroup.get('keys').setValue(this.keys);
|
|
||||||
this.modelValue.splice(index, 1);
|
this.modelValue.splice(index, 1);
|
||||||
|
this.keysListFormGroup.get('keys').setValue(this.keys);
|
||||||
if (!this.modelValue.length) {
|
if (!this.modelValue.length) {
|
||||||
this.modelValue = null;
|
this.modelValue = null;
|
||||||
}
|
}
|
||||||
@ -468,8 +506,8 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
index = this.keys.length;
|
index = this.keys.length;
|
||||||
}
|
}
|
||||||
moveItemInArray(this.keys, this.dragIndex, index);
|
moveItemInArray(this.keys, this.dragIndex, index);
|
||||||
this.keysListFormGroup.get('keys').setValue(this.keys);
|
|
||||||
moveItemInArray(this.modelValue, this.dragIndex, index);
|
moveItemInArray(this.modelValue, this.dragIndex, index);
|
||||||
|
this.keysListFormGroup.get('keys').setValue(this.keys);
|
||||||
this.dragIndex = -1;
|
this.dragIndex = -1;
|
||||||
this.propagateChange(this.modelValue);
|
this.propagateChange(this.modelValue);
|
||||||
}
|
}
|
||||||
@ -525,8 +563,8 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
|
|||||||
}).afterClosed().subscribe((updatedDataKey) => {
|
}).afterClosed().subscribe((updatedDataKey) => {
|
||||||
if (updatedDataKey) {
|
if (updatedDataKey) {
|
||||||
this.keys[index] = updatedDataKey;
|
this.keys[index] = updatedDataKey;
|
||||||
this.keysListFormGroup.get('keys').setValue(this.keys);
|
|
||||||
this.modelValue[index] = updatedDataKey;
|
this.modelValue[index] = updatedDataKey;
|
||||||
|
this.keysListFormGroup.get('keys').setValue(this.keys);
|
||||||
this.propagateChange(this.modelValue);
|
this.propagateChange(this.modelValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -435,6 +435,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
|
|||||||
this.basicModeComponentChangeSubscription = this.basicModeComponent.widgetConfigChanged.subscribe((data) => {
|
this.basicModeComponentChangeSubscription = this.basicModeComponent.widgetConfigChanged.subscribe((data) => {
|
||||||
this.modelValue = data;
|
this.modelValue = data;
|
||||||
this.propagateChange(this.modelValue);
|
this.propagateChange(this.modelValue);
|
||||||
|
this.cd.markForCheck();
|
||||||
});
|
});
|
||||||
this.cd.markForCheck();
|
this.cd.markForCheck();
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user