UI: Fixed widget config forms validation.

This commit is contained in:
Igor Kulikov 2023-11-08 13:50:47 +02:00
parent 4025a1f549
commit 43bdf120f2
5 changed files with 48 additions and 52 deletions

View File

@ -69,12 +69,12 @@ export abstract class BasicWidgetConfigComponent extends PageComponent implement
ngOnInit() {} ngOnInit() {}
ngAfterViewInit(): void { ngAfterViewInit(): void {
setTimeout(() => {
if (!this.validateConfig()) { if (!this.validateConfig()) {
setTimeout(() => {
this.onConfigChanged(this.prepareOutputConfig(this.configForm().getRawValue())); this.onConfigChanged(this.prepareOutputConfig(this.configForm().getRawValue()));
}
}, 0); }, 0);
} }
}
protected setupConfig(widgetConfig: WidgetConfigComponentData) { protected setupConfig(widgetConfig: WidgetConfigComponentData) {
if (this.isAdd) { if (this.isAdd) {

View File

@ -29,10 +29,14 @@ import {
ViewContainerRef ViewContainerRef
} from '@angular/core'; } from '@angular/core';
import { import {
AbstractControl,
ControlValueAccessor, ControlValueAccessor,
NG_VALIDATORS,
NG_VALUE_ACCESSOR, NG_VALUE_ACCESSOR,
UntypedFormBuilder, UntypedFormBuilder,
UntypedFormGroup, UntypedFormGroup,
ValidationErrors,
Validator,
Validators Validators
} from '@angular/forms'; } from '@angular/forms';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
@ -54,9 +58,14 @@ import { WidgetConfigComponentData } from '@home/models/widget-component.models'
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => WidgetSettingsComponent), useExisting: forwardRef(() => WidgetSettingsComponent),
multi: true multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => WidgetSettingsComponent),
multi: true
}] }]
}) })
export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, OnDestroy, AfterViewInit, OnChanges { export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, OnDestroy, AfterViewInit, OnChanges, Validator {
@ViewChild('definedSettingsContent', {read: ViewContainerRef, static: true}) definedSettingsContainer: ViewContainerRef; @ViewChild('definedSettingsContent', {read: ViewContainerRef, static: true}) definedSettingsContainer: ViewContainerRef;
@ -89,7 +98,6 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On
private definedSettingsComponent: IWidgetSettingsComponent; private definedSettingsComponent: IWidgetSettingsComponent;
private widgetSettingsFormData: JsonFormComponentData; private widgetSettingsFormData: JsonFormComponentData;
private propagateChange = (v: any) => { }; private propagateChange = (v: any) => { };
constructor(private translate: TranslateService, constructor(private translate: TranslateService,
@ -193,11 +201,7 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On
private updateModel(settings: WidgetSettings) { private updateModel(settings: WidgetSettings) {
this.widgetSettingsFormData.model = settings; this.widgetSettingsFormData.model = settings;
if (this.definedSettingsComponent || this.widgetSettingsFormGroup.valid) {
this.propagateChange(this.widgetSettingsFormData); this.propagateChange(this.widgetSettingsFormData);
} else {
this.propagateChange(null);
}
} }
private validateDefinedDirective() { private validateDefinedDirective() {
@ -232,9 +236,24 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On
} }
} }
validate() { validate(control: AbstractControl): ValidationErrors | null {
if (this.useDefinedDirective()) { if (this.useDefinedDirective()) {
this.definedSettingsComponent.validate(); if (!this.definedSettingsComponent.validateSettings()) {
return {
widgetSettings: {
valid: false
} }
};
}
} else if (this.useJsonForm()) {
if (!this.widgetSettingsFormGroup.valid) {
return {
widgetSettings: {
valid: false
}
};
}
}
return null;
} }
} }

View File

@ -115,7 +115,7 @@ export class PersistentTableWidgetSettingsComponent extends WidgetSettingsCompon
}); });
} }
protected validateSettings(): boolean { public validateSettings(): boolean {
const displayColumns: string[] = this.persistentTableWidgetSettingsForm.get('displayColumns').value; const displayColumns: string[] = this.persistentTableWidgetSettingsForm.get('displayColumns').value;
this.columnsChipList.errorState = !displayColumns?.length; this.columnsChipList.errorState = !displayColumns?.length;
return super.validateSettings(); return super.validateSettings();

View File

@ -903,7 +903,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
valid: false valid: false
} }
}; };
} else if (!this.advancedSettings.valid || (this.displayAdvancedAppearance && !this.modelValue.config.settings)) { } else if (!this.advancedSettings.valid) {
return { return {
advancedSettings: { advancedSettings: {
valid: false valid: false

View File

@ -38,7 +38,7 @@ import { AbstractControl, UntypedFormGroup } from '@angular/forms';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Dashboard } from '@shared/models/dashboard.models'; import { Dashboard } from '@shared/models/dashboard.models';
import { IAliasController } from '@core/api/widget-api.models'; import { IAliasController } from '@core/api/widget-api.models';
import { isEmptyStr, isNotEmptyStr } from '@core/utils'; import { isNotEmptyStr } from '@core/utils';
import { WidgetConfigComponentData } from '@home/models/widget-component.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models';
import { ComponentStyle, Font, TimewindowStyle } from '@shared/models/widget-settings.models'; import { ComponentStyle, Font, TimewindowStyle } from '@shared/models/widget-settings.models';
import { NULL_UUID } from '@shared/models/id/has-uuid'; import { NULL_UUID } from '@shared/models/id/has-uuid';
@ -750,23 +750,10 @@ export interface IWidgetSettingsComponent {
functionScopeVariables: string[]; functionScopeVariables: string[];
settings: WidgetSettings; settings: WidgetSettings;
settingsChanged: Observable<WidgetSettings>; settingsChanged: Observable<WidgetSettings>;
validate(); validateSettings(): boolean;
[key: string]: any; [key: string]: any;
} }
const removeEmptyWidgetSettings = (settings: WidgetSettings): WidgetSettings => {
if (settings) {
const keys = Object.keys(settings);
for (const key of keys) {
const val = settings[key];
if (val === null || isEmptyStr(val)) {
delete settings[key];
}
}
}
return settings;
};
@Directive() @Directive()
// eslint-disable-next-line @angular-eslint/directive-class-suffix // eslint-disable-next-line @angular-eslint/directive-class-suffix
export abstract class WidgetSettingsComponent extends PageComponent implements export abstract class WidgetSettingsComponent extends PageComponent implements
@ -823,15 +810,15 @@ export abstract class WidgetSettingsComponent extends PageComponent implements
ngOnInit() {} ngOnInit() {}
ngAfterViewInit(): void { ngAfterViewInit(): void {
setTimeout(() => {
if (!this.validateSettings()) { if (!this.validateSettings()) {
this.settingsChangedEmitter.emit(null); setTimeout(() => {
} this.onSettingsChanged(this.prepareOutputSettings(this.settingsForm().getRawValue()));
}, 0); }, 0);
} }
}
validate() { public validateSettings(): boolean {
this.onValidate(); return this.settingsForm().valid;
} }
protected setupSettings(settings: WidgetSettings) { protected setupSettings(settings: WidgetSettings) {
@ -847,8 +834,8 @@ export abstract class WidgetSettingsComponent extends PageComponent implements
this.updateValidators(true, trigger); this.updateValidators(true, trigger);
}); });
} }
this.settingsForm().valueChanges.subscribe((updated: any) => { this.settingsForm().valueChanges.subscribe(() => {
this.onSettingsChanged(this.prepareOutputSettings(updated)); this.onSettingsChanged(this.prepareOutputSettings(this.settingsForm().getRawValue()));
}); });
} }
@ -867,12 +854,8 @@ export abstract class WidgetSettingsComponent extends PageComponent implements
} }
protected onSettingsChanged(updated: WidgetSettings) { protected onSettingsChanged(updated: WidgetSettings) {
this.settingsValue = removeEmptyWidgetSettings(updated); this.settingsValue = updated;
if (this.validateSettings()) {
this.settingsChangedEmitter.emit(this.settingsValue); this.settingsChangedEmitter.emit(this.settingsValue);
} else {
this.settingsChangedEmitter.emit(null);
}
} }
protected doUpdateSettings(settingsForm: UntypedFormGroup, settings: WidgetSettings) { protected doUpdateSettings(settingsForm: UntypedFormGroup, settings: WidgetSettings) {
@ -886,12 +869,6 @@ export abstract class WidgetSettingsComponent extends PageComponent implements
return settings; return settings;
} }
protected validateSettings(): boolean {
return this.settingsForm().valid;
}
protected onValidate() {}
protected abstract settingsForm(): UntypedFormGroup; protected abstract settingsForm(): UntypedFormGroup;
protected abstract onSettingsSet(settings: WidgetSettings); protected abstract onSettingsSet(settings: WidgetSettings);