From bbbeee4fe9da55d6883058203e4263adebb0ee42 Mon Sep 17 00:00:00 2001 From: mohamedsalem401 Date: Fri, 27 Dec 2024 00:37:34 +0200 Subject: [PATCH] Refactor component dynamic values --- .../src/dom_components/model/Component.ts | 42 +++++++++++-------- .../model/ComponentDynamicValueWatcher.ts | 26 ++++++------ .../model/DynamicValueWatcher.ts | 30 +++++++++---- 3 files changed, 57 insertions(+), 41 deletions(-) diff --git a/packages/core/src/dom_components/model/Component.ts b/packages/core/src/dom_components/model/Component.ts index 99e7c1e1d..c59408d44 100644 --- a/packages/core/src/dom_components/model/Component.ts +++ b/packages/core/src/dom_components/model/Component.ts @@ -51,15 +51,16 @@ import { updateSymbolComps, updateSymbolProps, } from './SymbolUtils'; -import { ComponentDynamicValueWatcher } from './ComponentDynamicValueListener'; +import { ComponentDynamicValueWatcher } from './ComponentDynamicValueWatcher'; import { DynamicValueWatcher } from './DynamicValueWatcher'; -export interface IComponent extends ExtractMethods { } +export interface IComponent extends ExtractMethods {} export interface DynamicWatchersOptions { skipWatcherUpdates?: boolean; + fromDataSource?: boolean; } -export interface SetAttrOptions extends SetOptions, UpdateStyleOptions, DynamicWatchersOptions { } -export interface ComponentSetOptions extends SetOptions, DynamicWatchersOptions { } +export interface SetAttrOptions extends SetOptions, UpdateStyleOptions, DynamicWatchersOptions {} +export interface ComponentSetOptions extends SetOptions, DynamicWatchersOptions {} const escapeRegExp = (str: string) => { return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'); @@ -226,12 +227,12 @@ export default class Component extends StyleableModel { return this.frame?.getPage(); } - preInit() { } + preInit() {} /** * Hook method, called once the model is created */ - init() { } + init() {} /** * Hook method, called when the model has been updated (eg. updated some model's property) @@ -239,12 +240,12 @@ export default class Component extends StyleableModel { * @param {*} value Property value, if triggered after some property update * @param {*} previous Property previous value, if triggered after some property update */ - updated(property: string, value: any, previous: any) { } + updated(property: string, value: any, previous: any) {} /** * Hook method, called once the model has been removed */ - removed() { } + removed() {} em!: EditorModel; opt!: ComponentOptions; @@ -264,8 +265,7 @@ export default class Component extends StyleableModel { componentDVListener: ComponentDynamicValueWatcher; constructor(props: ComponentProperties = {}, opt: ComponentOptions) { - const evaluatedProps = ComponentDynamicValueWatcher.evaluateComponentDef(props, opt.em); - super(evaluatedProps, opt); + super(props, opt); this.componentDVListener = new ComponentDynamicValueWatcher(this, opt.em); this.componentDVListener.watchComponentDef(props); @@ -295,7 +295,7 @@ export default class Component extends StyleableModel { this.opt = opt; this.em = em!; this.config = opt.config || {}; - this.set('attributes', { + this.setAttributes({ ...(result(this, 'defaults').attributes || {}), ...(this.get('attributes') || {}), }); @@ -343,7 +343,7 @@ export default class Component extends StyleableModel { optionsOrUndefined?: ComponentSetOptions, ): this { let attributes: Partial; - let options: ComponentSetOptions = { skipWatcherUpdates: false }; + let options: ComponentSetOptions = { skipWatcherUpdates: false, fromDataSource: false }; if (typeof keyOrAttributes === 'object') { attributes = keyOrAttributes; options = valueOrOptions || (options as ComponentSetOptions); @@ -360,11 +360,14 @@ export default class Component extends StyleableModel { if (areStaticAttributes) { evaluatedAttributes = attributes; } else { - evaluatedAttributes = ComponentDynamicValueWatcher.evaluateComponentDef(attributes, this.em); + // @ts-ignore + const em = this.em || options.em; + evaluatedAttributes = ComponentDynamicValueWatcher.evaluateComponentDef(attributes, em); } - if (!options.skipWatcherUpdates) { - this.componentDVListener?.watchProps(attributes); + const shouldSkipWatcherUpdates = options.skipWatcherUpdates || options.fromDataSource; + if (!shouldSkipWatcherUpdates) { + this.componentDVListener?.addProps(attributes); } return super.set(evaluatedAttributes, options); @@ -687,9 +690,12 @@ export default class Component extends StyleableModel { * @example * component.setAttributes({ id: 'test', 'data-key': 'value' }); */ - setAttributes(attrs: ObjectAny, opts: SetAttrOptions = { skipWatcherUpdates: false }) { - const evaluatedAttributes = DynamicValueWatcher.getStaticValues(attrs, this.em); - if (!opts.skipWatcherUpdates) { + setAttributes(attrs: ObjectAny, opts: SetAttrOptions = { skipWatcherUpdates: false, fromDataSource: false }) { + // @ts-ignore + const em = this.em || opts.em; + const evaluatedAttributes = DynamicValueWatcher.getStaticValues(attrs, em); + const shouldSkipWatcherUpdates = opts.skipWatcherUpdates || opts.fromDataSource; + if (!shouldSkipWatcherUpdates) { this.componentDVListener.setAttributes(attrs); } this.set('attributes', { ...evaluatedAttributes }, opts); diff --git a/packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts b/packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts index 6fcdbb493..a78e2a50f 100644 --- a/packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts +++ b/packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts @@ -19,13 +19,13 @@ export class ComponentDynamicValueWatcher { private createPropertyUpdater() { return (key: string, value: any) => { - this.component.set(key, value, { skipWatcherUpdates: false, avoidStore: true }); + this.component.set(key, value, { skipWatcherUpdates: true, avoidStore: true }); }; } private createAttributeUpdater() { return (key: string, value: any) => { - this.component.addAttributes({ [key]: value }, { skipWatcherUpdates: false }); + this.component.addAttributes({ [key]: value }, { skipWatcherUpdates: true, avoidStore: true }); }; } @@ -64,14 +64,13 @@ export class ComponentDynamicValueWatcher { } watchComponentDef(values: ObjectAny) { - this.watchProps(values); - this.watchAttributes(values.attributes); - this.watchTraits(values.traits); + this.addProps(values); + this.addAttributes(values.attributes); + this.addTraits(values.traits); } - watchProps(props: ObjectAny) { - this.propertyWatcher.removeListeners(Object.keys(props)); - this.propertyWatcher.watchDynamicValue(props); + addProps(props: ObjectAny) { + this.propertyWatcher.addDynamicValues(props); } getDynamicPropsDefs() { @@ -79,15 +78,14 @@ export class ComponentDynamicValueWatcher { } setAttributes(attributes: ObjectAny) { - this.attributeWatcher.removeListeners(); - this.attributeWatcher.watchDynamicValue(attributes); + this.attributeWatcher.setDynamicValues(attributes); } - watchAttributes(attributes: ObjectAny) { - this.attributeWatcher.watchDynamicValue(attributes); + addAttributes(attributes: ObjectAny) { + this.attributeWatcher.addDynamicValues(attributes); } - watchTraits(traits: (string | ObjectAny)[]) { + addTraits(traits: (string | ObjectAny)[]) { const evaluatedTraits: { [key: string]: ObjectAny } = {}; traits?.forEach((trait: any) => { @@ -96,7 +94,7 @@ export class ComponentDynamicValueWatcher { } }); - this.traitsWatcher.watchDynamicValue(evaluatedTraits); + this.traitsWatcher.addDynamicValues(evaluatedTraits); } removeAttributes(attributes: string[]) { diff --git a/packages/core/src/dom_components/model/DynamicValueWatcher.ts b/packages/core/src/dom_components/model/DynamicValueWatcher.ts index 2aaa121c0..b7d3e7cc7 100644 --- a/packages/core/src/dom_components/model/DynamicValueWatcher.ts +++ b/packages/core/src/dom_components/model/DynamicValueWatcher.ts @@ -1,6 +1,7 @@ import { ObjectAny } from '../../common'; import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager'; import { evaluateDynamicValueDefinition, isDynamicValueDefinition } from '../../data_sources/model/utils'; +import { DynamicValue } from '../../data_sources/types'; import EditorModel from '../../editor/model/Editor'; export class DynamicValueWatcher { @@ -10,7 +11,8 @@ export class DynamicValueWatcher { private em: EditorModel, ) {} - static getStaticValues(values: ObjectAny, em: EditorModel): ObjectAny { + static getStaticValues(values: ObjectAny | undefined, em: EditorModel): ObjectAny { + if (!values) return {}; const evaluatedValues: ObjectAny = { ...values }; const propsKeys = Object.keys(values); @@ -25,13 +27,21 @@ export class DynamicValueWatcher { return evaluatedValues; } - static areStaticValues(values: ObjectAny) { + static areStaticValues(values: ObjectAny | undefined) { + if (!values) return true; return Object.keys(values).every((key) => { return !isDynamicValueDefinition(values[key]); }); } - watchDynamicValue(values: ObjectAny) { + setDynamicValues(values: ObjectAny | undefined) { + this.removeListeners(); + return this.addDynamicValues(values); + } + + addDynamicValues(values: ObjectAny | undefined) { + if (!values) return {}; + this.removeListeners(Object.keys(values)); const dynamicProps = this.getDynamicValues(values); const propsKeys = Object.keys(dynamicProps); for (let index = 0; index < propsKeys.length; index++) { @@ -50,15 +60,16 @@ export class DynamicValueWatcher { } private getDynamicValues(values: ObjectAny) { - const dynamicValues = { ...values }; - const propsKeys = Object.keys(dynamicValues); + const dynamicValues: { + [key: string]: DynamicValue; + } = {}; + const propsKeys = Object.keys(values); for (let index = 0; index < propsKeys.length; index++) { const key = propsKeys[index]; - if (!isDynamicValueDefinition(dynamicValues[key])) { - delete dynamicValues[key]; + if (!isDynamicValueDefinition(values[key])) { continue; } - const { variable } = evaluateDynamicValueDefinition(dynamicValues[key], this.em); + const { variable } = evaluateDynamicValueDefinition(values[key], this.em); dynamicValues[key] = variable; } @@ -80,7 +91,8 @@ export class DynamicValueWatcher { }); } - getSerializableValues(values: ObjectAny) { + getSerializableValues(values: ObjectAny | undefined) { + if (!values) return {}; const serializableValues = { ...values }; const propsKeys = Object.keys(serializableValues); for (let index = 0; index < propsKeys.length; index++) {