Browse Source

Refactor component dynamic values

pull/6351/head
mohamedsalem401 1 year ago
parent
commit
bbbeee4fe9
  1. 42
      packages/core/src/dom_components/model/Component.ts
  2. 26
      packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts
  3. 30
      packages/core/src/dom_components/model/DynamicValueWatcher.ts

42
packages/core/src/dom_components/model/Component.ts

@ -51,15 +51,16 @@ import {
updateSymbolComps, updateSymbolComps,
updateSymbolProps, updateSymbolProps,
} from './SymbolUtils'; } from './SymbolUtils';
import { ComponentDynamicValueWatcher } from './ComponentDynamicValueListener'; import { ComponentDynamicValueWatcher } from './ComponentDynamicValueWatcher';
import { DynamicValueWatcher } from './DynamicValueWatcher'; import { DynamicValueWatcher } from './DynamicValueWatcher';
export interface IComponent extends ExtractMethods<Component> { } export interface IComponent extends ExtractMethods<Component> {}
export interface DynamicWatchersOptions { export interface DynamicWatchersOptions {
skipWatcherUpdates?: boolean; skipWatcherUpdates?: boolean;
fromDataSource?: boolean;
} }
export interface SetAttrOptions extends SetOptions, UpdateStyleOptions, DynamicWatchersOptions { } export interface SetAttrOptions extends SetOptions, UpdateStyleOptions, DynamicWatchersOptions {}
export interface ComponentSetOptions extends SetOptions, DynamicWatchersOptions { } export interface ComponentSetOptions extends SetOptions, DynamicWatchersOptions {}
const escapeRegExp = (str: string) => { const escapeRegExp = (str: string) => {
return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'); return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
@ -226,12 +227,12 @@ export default class Component extends StyleableModel<ComponentProperties> {
return this.frame?.getPage(); return this.frame?.getPage();
} }
preInit() { } preInit() {}
/** /**
* Hook method, called once the model is created * 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) * 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<ComponentProperties> {
* @param {*} value Property value, if triggered after some property update * @param {*} value Property value, if triggered after some property update
* @param {*} previous Property previous 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 * Hook method, called once the model has been removed
*/ */
removed() { } removed() {}
em!: EditorModel; em!: EditorModel;
opt!: ComponentOptions; opt!: ComponentOptions;
@ -264,8 +265,7 @@ export default class Component extends StyleableModel<ComponentProperties> {
componentDVListener: ComponentDynamicValueWatcher; componentDVListener: ComponentDynamicValueWatcher;
constructor(props: ComponentProperties = {}, opt: ComponentOptions) { constructor(props: ComponentProperties = {}, opt: ComponentOptions) {
const evaluatedProps = ComponentDynamicValueWatcher.evaluateComponentDef(props, opt.em); super(props, opt);
super(evaluatedProps, opt);
this.componentDVListener = new ComponentDynamicValueWatcher(this, opt.em); this.componentDVListener = new ComponentDynamicValueWatcher(this, opt.em);
this.componentDVListener.watchComponentDef(props); this.componentDVListener.watchComponentDef(props);
@ -295,7 +295,7 @@ export default class Component extends StyleableModel<ComponentProperties> {
this.opt = opt; this.opt = opt;
this.em = em!; this.em = em!;
this.config = opt.config || {}; this.config = opt.config || {};
this.set('attributes', { this.setAttributes({
...(result(this, 'defaults').attributes || {}), ...(result(this, 'defaults').attributes || {}),
...(this.get('attributes') || {}), ...(this.get('attributes') || {}),
}); });
@ -343,7 +343,7 @@ export default class Component extends StyleableModel<ComponentProperties> {
optionsOrUndefined?: ComponentSetOptions, optionsOrUndefined?: ComponentSetOptions,
): this { ): this {
let attributes: Partial<ComponentProperties>; let attributes: Partial<ComponentProperties>;
let options: ComponentSetOptions = { skipWatcherUpdates: false }; let options: ComponentSetOptions = { skipWatcherUpdates: false, fromDataSource: false };
if (typeof keyOrAttributes === 'object') { if (typeof keyOrAttributes === 'object') {
attributes = keyOrAttributes; attributes = keyOrAttributes;
options = valueOrOptions || (options as ComponentSetOptions); options = valueOrOptions || (options as ComponentSetOptions);
@ -360,11 +360,14 @@ export default class Component extends StyleableModel<ComponentProperties> {
if (areStaticAttributes) { if (areStaticAttributes) {
evaluatedAttributes = attributes; evaluatedAttributes = attributes;
} else { } else {
evaluatedAttributes = ComponentDynamicValueWatcher.evaluateComponentDef(attributes, this.em); // @ts-ignore
const em = this.em || options.em;
evaluatedAttributes = ComponentDynamicValueWatcher.evaluateComponentDef(attributes, em);
} }
if (!options.skipWatcherUpdates) { const shouldSkipWatcherUpdates = options.skipWatcherUpdates || options.fromDataSource;
this.componentDVListener?.watchProps(attributes); if (!shouldSkipWatcherUpdates) {
this.componentDVListener?.addProps(attributes);
} }
return super.set(evaluatedAttributes, options); return super.set(evaluatedAttributes, options);
@ -687,9 +690,12 @@ export default class Component extends StyleableModel<ComponentProperties> {
* @example * @example
* component.setAttributes({ id: 'test', 'data-key': 'value' }); * component.setAttributes({ id: 'test', 'data-key': 'value' });
*/ */
setAttributes(attrs: ObjectAny, opts: SetAttrOptions = { skipWatcherUpdates: false }) { setAttributes(attrs: ObjectAny, opts: SetAttrOptions = { skipWatcherUpdates: false, fromDataSource: false }) {
const evaluatedAttributes = DynamicValueWatcher.getStaticValues(attrs, this.em); // @ts-ignore
if (!opts.skipWatcherUpdates) { 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.componentDVListener.setAttributes(attrs);
} }
this.set('attributes', { ...evaluatedAttributes }, opts); this.set('attributes', { ...evaluatedAttributes }, opts);

26
packages/core/src/dom_components/model/ComponentDynamicValueWatcher.ts

@ -19,13 +19,13 @@ export class ComponentDynamicValueWatcher {
private createPropertyUpdater() { private createPropertyUpdater() {
return (key: string, value: any) => { 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() { private createAttributeUpdater() {
return (key: string, value: any) => { 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) { watchComponentDef(values: ObjectAny) {
this.watchProps(values); this.addProps(values);
this.watchAttributes(values.attributes); this.addAttributes(values.attributes);
this.watchTraits(values.traits); this.addTraits(values.traits);
} }
watchProps(props: ObjectAny) { addProps(props: ObjectAny) {
this.propertyWatcher.removeListeners(Object.keys(props)); this.propertyWatcher.addDynamicValues(props);
this.propertyWatcher.watchDynamicValue(props);
} }
getDynamicPropsDefs() { getDynamicPropsDefs() {
@ -79,15 +78,14 @@ export class ComponentDynamicValueWatcher {
} }
setAttributes(attributes: ObjectAny) { setAttributes(attributes: ObjectAny) {
this.attributeWatcher.removeListeners(); this.attributeWatcher.setDynamicValues(attributes);
this.attributeWatcher.watchDynamicValue(attributes);
} }
watchAttributes(attributes: ObjectAny) { addAttributes(attributes: ObjectAny) {
this.attributeWatcher.watchDynamicValue(attributes); this.attributeWatcher.addDynamicValues(attributes);
} }
watchTraits(traits: (string | ObjectAny)[]) { addTraits(traits: (string | ObjectAny)[]) {
const evaluatedTraits: { [key: string]: ObjectAny } = {}; const evaluatedTraits: { [key: string]: ObjectAny } = {};
traits?.forEach((trait: any) => { traits?.forEach((trait: any) => {
@ -96,7 +94,7 @@ export class ComponentDynamicValueWatcher {
} }
}); });
this.traitsWatcher.watchDynamicValue(evaluatedTraits); this.traitsWatcher.addDynamicValues(evaluatedTraits);
} }
removeAttributes(attributes: string[]) { removeAttributes(attributes: string[]) {

30
packages/core/src/dom_components/model/DynamicValueWatcher.ts

@ -1,6 +1,7 @@
import { ObjectAny } from '../../common'; import { ObjectAny } from '../../common';
import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager'; import DynamicVariableListenerManager from '../../data_sources/model/DataVariableListenerManager';
import { evaluateDynamicValueDefinition, isDynamicValueDefinition } from '../../data_sources/model/utils'; import { evaluateDynamicValueDefinition, isDynamicValueDefinition } from '../../data_sources/model/utils';
import { DynamicValue } from '../../data_sources/types';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
export class DynamicValueWatcher { export class DynamicValueWatcher {
@ -10,7 +11,8 @@ export class DynamicValueWatcher {
private em: EditorModel, 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 evaluatedValues: ObjectAny = { ...values };
const propsKeys = Object.keys(values); const propsKeys = Object.keys(values);
@ -25,13 +27,21 @@ export class DynamicValueWatcher {
return evaluatedValues; return evaluatedValues;
} }
static areStaticValues(values: ObjectAny) { static areStaticValues(values: ObjectAny | undefined) {
if (!values) return true;
return Object.keys(values).every((key) => { return Object.keys(values).every((key) => {
return !isDynamicValueDefinition(values[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 dynamicProps = this.getDynamicValues(values);
const propsKeys = Object.keys(dynamicProps); const propsKeys = Object.keys(dynamicProps);
for (let index = 0; index < propsKeys.length; index++) { for (let index = 0; index < propsKeys.length; index++) {
@ -50,15 +60,16 @@ export class DynamicValueWatcher {
} }
private getDynamicValues(values: ObjectAny) { private getDynamicValues(values: ObjectAny) {
const dynamicValues = { ...values }; const dynamicValues: {
const propsKeys = Object.keys(dynamicValues); [key: string]: DynamicValue;
} = {};
const propsKeys = Object.keys(values);
for (let index = 0; index < propsKeys.length; index++) { for (let index = 0; index < propsKeys.length; index++) {
const key = propsKeys[index]; const key = propsKeys[index];
if (!isDynamicValueDefinition(dynamicValues[key])) { if (!isDynamicValueDefinition(values[key])) {
delete dynamicValues[key];
continue; continue;
} }
const { variable } = evaluateDynamicValueDefinition(dynamicValues[key], this.em); const { variable } = evaluateDynamicValueDefinition(values[key], this.em);
dynamicValues[key] = variable; dynamicValues[key] = variable;
} }
@ -80,7 +91,8 @@ export class DynamicValueWatcher {
}); });
} }
getSerializableValues(values: ObjectAny) { getSerializableValues(values: ObjectAny | undefined) {
if (!values) return {};
const serializableValues = { ...values }; const serializableValues = { ...values };
const propsKeys = Object.keys(serializableValues); const propsKeys = Object.keys(serializableValues);
for (let index = 0; index < propsKeys.length; index++) { for (let index = 0; index < propsKeys.length; index++) {

Loading…
Cancel
Save