From f34d7f4d9c4cd93c793f198e2d508bdb8917a7d8 Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 9 Mar 2022 14:23:00 -0700 Subject: [PATCH] Solution for boolean attributes that need row data: Use the default but hold on to the value that couldn't be parsed, defer processing until later. --- api/js/etemplate/Et2Widget/Et2Widget.ts | 32 ++++++++++++++++ .../et2_extension_nextmatch_rowProvider.ts | 37 +++++++++++++------ 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/api/js/etemplate/Et2Widget/Et2Widget.ts b/api/js/etemplate/Et2Widget/Et2Widget.ts index 18732c8499..d8c5d786d4 100644 --- a/api/js/etemplate/Et2Widget/Et2Widget.ts +++ b/api/js/etemplate/Et2Widget/Et2Widget.ts @@ -76,6 +76,13 @@ const Et2WidgetMixin = (superClass) => protected _dom_id : string = ""; private statustext : string = ""; + /** + * TypeScript & LitElement ensure type correctness, so we can't have a string value like "$row_cont[disable_me]" + * as a boolean property so we store them here, and parse them when expanding. Strings do not have this problem, + * since $row_cont[disable_me] is still a valid string. + */ + protected _deferred_properties : { [key : string] : string } = {}; + /** WebComponent **/ static get styles() @@ -343,6 +350,20 @@ const Et2WidgetMixin = (superClass) => } } + /** + * Any attribute that refers to row content cannot be resolved immediately, but some like booleans cannot stay a + * string because it's a boolean attribute. We store them for later, and parse when they're fully in their row. + */ + get deferredProperties() + { + return this._deferred_properties; + } + + set deferredProperties(value) + { + this._deferred_properties = value; + } + /** * Do some fancy stuff on the label, splitting it up if there's a %s in it * @@ -963,6 +984,9 @@ const Et2WidgetMixin = (superClass) => copy[key] = this[key]; } + // Keep the deferred properties + copy._deferred_properties = this._deferred_properties; + // Create a clone of all child widgets of the given object for(let i = 0; i < this.getChildren().length; i++) { @@ -1276,6 +1300,14 @@ function transformAttributes(widget, mgr : et2_arrayMgr, attributes) // If the attribute is marked as boolean, parse the // expression as bool expression. attrValue = mgr ? mgr.parseBoolExpression(attrValue) : attrValue; + if(typeof attrValue === "string") + { + // Parse decided we still needed a string ($row most likely) so we'll defer it until later + // Repeating rows & nextmatch will parse it again when doing the row + widget.deferredProperties[attribute] = attrValue; + // Leave the current value at whatever the default is + continue; + } break; case Function: // We parse it into a function here so we can pass in the widget as context. diff --git a/api/js/etemplate/et2_extension_nextmatch_rowProvider.ts b/api/js/etemplate/et2_extension_nextmatch_rowProvider.ts index 4e6b81996a..2524dadd0b 100644 --- a/api/js/etemplate/et2_extension_nextmatch_rowProvider.ts +++ b/api/js/etemplate/et2_extension_nextmatch_rowProvider.ts @@ -23,7 +23,6 @@ import {et2_arrayMgrs_expand} from "./et2_core_arrayMgr"; import {et2_dataview_grid} from "./et2_dataview_view_grid"; import {egw} from "../jsapi/egw_global"; import {et2_IDetachedDOM, et2_IDOMNode} from "./et2_core_interfaces"; -import {Et2DateTimeReadonly} from "./Et2Date/Et2DateTimeReadonly"; /** * The row provider contains prototypes (full clonable dom-trees) @@ -180,17 +179,7 @@ export class et2_nextmatch_rowProvider // WebComponent IS the node, and we've already cloned it if(typeof window.customElements.get(widget.localName) != "undefined") { - /* - // N.B. cloneNode widget is missing its unreflected properties and we need to use widget.clone() - // instead to get them. This slows things down. - let c = widget.clone(); - let partial = entry.nodeFuncs[0](row); - partial.parentNode.insertBefore(c, partial); - partial.parentNode.removeChild(partial); - widget = c; - */ - // Use the clone, not the original - widget = entry.nodeFuncs[0](row); + widget = this._cloneWebComponent(entry, row, data); } else { @@ -267,6 +256,30 @@ export class et2_nextmatch_rowProvider return rowWidget; } + /** + * Get the cloned web component + */ + _cloneWebComponent(entry, row, data) + { + /* + // N.B. cloneNode widget is missing its unreflected properties and we need to use widget.clone() + // instead to get them. This slows things down and is to be avoided if we can. + let c = widget.clone(); + let partial = entry.nodeFuncs[0](row); + partial.parentNode.insertBefore(c, partial); + partial.parentNode.removeChild(partial); + widget = c; + */ + + // Use the clone, not the original + let widget = entry.nodeFuncs[0](row); + + // Deal with the deferred properties like booleans with string values - we can't reflect them, and we don't want to lose them + // No need to transform here, that happens later + Object.assign(data, entry.widget.deferredProperties); + + return widget; + } /** * Placeholder for empty row