From 43bdf120f213a3d07ef9e025614ed8ed7618d024 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 8 Nov 2023 13:50:47 +0200 Subject: [PATCH] UI: Fixed widget config forms validation. --- .../config/widget-config.component.models.ts | 10 ++-- .../config/widget-settings.component.ts | 37 ++++++++++---- ...sistent-table-widget-settings.component.ts | 2 +- .../widget/widget-config.component.ts | 2 +- ui-ngx/src/app/shared/models/widget.models.ts | 49 +++++-------------- 5 files changed, 48 insertions(+), 52 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/config/widget-config.component.models.ts b/ui-ngx/src/app/modules/home/components/widget/config/widget-config.component.models.ts index cfa0cedbee..d021af6b20 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/widget-config.component.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/widget-config.component.models.ts @@ -69,11 +69,11 @@ export abstract class BasicWidgetConfigComponent extends PageComponent implement ngOnInit() {} ngAfterViewInit(): void { - setTimeout(() => { - if (!this.validateConfig()) { - this.onConfigChanged(this.prepareOutputConfig(this.configForm().getRawValue())); - } - }, 0); + if (!this.validateConfig()) { + setTimeout(() => { + this.onConfigChanged(this.prepareOutputConfig(this.configForm().getRawValue())); + }, 0); + } } protected setupConfig(widgetConfig: WidgetConfigComponentData) { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts index bf2144cdfd..65480ec3b8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts @@ -29,10 +29,14 @@ import { ViewContainerRef } from '@angular/core'; import { + AbstractControl, ControlValueAccessor, + NG_VALIDATORS, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup, + ValidationErrors, + Validator, Validators } from '@angular/forms'; import { Subscription } from 'rxjs'; @@ -54,9 +58,14 @@ import { WidgetConfigComponentData } from '@home/models/widget-component.models' provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => WidgetSettingsComponent), 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; @@ -89,7 +98,6 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On private definedSettingsComponent: IWidgetSettingsComponent; private widgetSettingsFormData: JsonFormComponentData; - private propagateChange = (v: any) => { }; constructor(private translate: TranslateService, @@ -193,11 +201,7 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On private updateModel(settings: WidgetSettings) { this.widgetSettingsFormData.model = settings; - if (this.definedSettingsComponent || this.widgetSettingsFormGroup.valid) { - this.propagateChange(this.widgetSettingsFormData); - } else { - this.propagateChange(null); - } + this.propagateChange(this.widgetSettingsFormData); } private validateDefinedDirective() { @@ -232,9 +236,24 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On } } - validate() { + validate(control: AbstractControl): ValidationErrors | null { 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; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.ts index b275e35973..8989794e86 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/persistent-table-widget-settings.component.ts @@ -115,7 +115,7 @@ export class PersistentTableWidgetSettingsComponent extends WidgetSettingsCompon }); } - protected validateSettings(): boolean { + public validateSettings(): boolean { const displayColumns: string[] = this.persistentTableWidgetSettingsForm.get('displayColumns').value; this.columnsChipList.errorState = !displayColumns?.length; return super.validateSettings(); diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts index 0f569c5ce9..889435be73 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts @@ -903,7 +903,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe valid: false } }; - } else if (!this.advancedSettings.valid || (this.displayAdvancedAppearance && !this.modelValue.config.settings)) { + } else if (!this.advancedSettings.valid) { return { advancedSettings: { valid: false diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 34829dd850..5e860a2930 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -38,7 +38,7 @@ import { AbstractControl, UntypedFormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; import { Dashboard } from '@shared/models/dashboard.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 { ComponentStyle, Font, TimewindowStyle } from '@shared/models/widget-settings.models'; import { NULL_UUID } from '@shared/models/id/has-uuid'; @@ -750,23 +750,10 @@ export interface IWidgetSettingsComponent { functionScopeVariables: string[]; settings: WidgetSettings; settingsChanged: Observable; - validate(); + validateSettings(): boolean; [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() // eslint-disable-next-line @angular-eslint/directive-class-suffix export abstract class WidgetSettingsComponent extends PageComponent implements @@ -823,15 +810,15 @@ export abstract class WidgetSettingsComponent extends PageComponent implements ngOnInit() {} ngAfterViewInit(): void { - setTimeout(() => { - if (!this.validateSettings()) { - this.settingsChangedEmitter.emit(null); - } - }, 0); + if (!this.validateSettings()) { + setTimeout(() => { + this.onSettingsChanged(this.prepareOutputSettings(this.settingsForm().getRawValue())); + }, 0); + } } - validate() { - this.onValidate(); + public validateSettings(): boolean { + return this.settingsForm().valid; } protected setupSettings(settings: WidgetSettings) { @@ -847,8 +834,8 @@ export abstract class WidgetSettingsComponent extends PageComponent implements this.updateValidators(true, trigger); }); } - this.settingsForm().valueChanges.subscribe((updated: any) => { - this.onSettingsChanged(this.prepareOutputSettings(updated)); + this.settingsForm().valueChanges.subscribe(() => { + this.onSettingsChanged(this.prepareOutputSettings(this.settingsForm().getRawValue())); }); } @@ -867,12 +854,8 @@ export abstract class WidgetSettingsComponent extends PageComponent implements } protected onSettingsChanged(updated: WidgetSettings) { - this.settingsValue = removeEmptyWidgetSettings(updated); - if (this.validateSettings()) { - this.settingsChangedEmitter.emit(this.settingsValue); - } else { - this.settingsChangedEmitter.emit(null); - } + this.settingsValue = updated; + this.settingsChangedEmitter.emit(this.settingsValue); } protected doUpdateSettings(settingsForm: UntypedFormGroup, settings: WidgetSettings) { @@ -886,12 +869,6 @@ export abstract class WidgetSettingsComponent extends PageComponent implements return settings; } - protected validateSettings(): boolean { - return this.settingsForm().valid; - } - - protected onValidate() {} - protected abstract settingsForm(): UntypedFormGroup; protected abstract onSettingsSet(settings: WidgetSettings);