From 96c2fb66d8d89b32825f5d628a3b12340ba0bd56 Mon Sep 17 00:00:00 2001 From: Daniel Kostro Date: Wed, 17 Sep 2025 09:20:30 +0200 Subject: [PATCH] fix(twig): make sure twig has finished rendering before setting the form data --- .../types/display/template-twig/view.js | 32 +- .../data/twig-form-timing-onload/view.json | 652 +++++++++++++++++- 2 files changed, 649 insertions(+), 35 deletions(-) diff --git a/src/modules/types/display/template-twig/view.js b/src/modules/types/display/template-twig/view.js index 8f662b5e5..75c30daaf 100644 --- a/src/modules/types/display/template-twig/view.js +++ b/src/modules/types/display/template-twig/view.js @@ -89,8 +89,9 @@ define([ }, rerender() { + const data = this.getForm(); this.render(() => { - this.resetForm(); + this.form.setData(data); }); }, @@ -104,10 +105,6 @@ define([ }); }, - setForm(data) { - this.form.setData(data); - }, - resetForm() { this.form.setData(this.currentForm); }, @@ -141,9 +138,8 @@ define([ return this.currentForm; }, - submitChange(event, noChange) { + submitChange(event) { if (!event) return; - event = event || { target: {} }; const toSend = { data: this.getForm(), }; @@ -157,7 +153,7 @@ define([ this._changedJpaths.add(event.target.name); } - this.module.controller.onFormChanged(toSend, noChange); + this.module.controller.onFormChanged(toSend); return null; }, @@ -209,15 +205,6 @@ define([ this._values[name] = DataObject.resurrect(value.get()); this.rerender(); - - if ( - this.module.getConfigurationCheckbox( - 'formOptions', - 'rerenderIfValueChanges', - ) - ) { - this.render(() => this.fillForm(true)); - } }, tpl(value) { var tpl = value.get().toString(); @@ -245,15 +232,17 @@ define([ // It doesn't make sense otherwise await this.hasTemplate; - this.fillForm(true); if ( this.module.getConfigurationCheckbox( 'formOptions', 'rerenderIfFormValueChanges', ) ) { - this.rerender(); + await this.rerender(); + } else { + await this.renderPromise; } + this.setDataAndTrackChanges(); }, style(value) { @@ -275,17 +264,16 @@ define([ 'setForm invalid arguments. Must be object with data property.', ); } - this.setForm(options.data); + this.form.setData(options.data); if (options.submitChange) { this.submitChange(); } }, }, - fillForm(noChange) { + setDataAndTrackChanges() { const changed = this.form.setData(this.formObject); for (const c of changed) this._changedJpaths.add(c); - this.submitChange(null, noChange); }, render(cb) { diff --git a/testcase/data/twig-form-timing-onload/view.json b/testcase/data/twig-form-timing-onload/view.json index 606fead52..59a4b9a88 100644 --- a/testcase/data/twig-form-timing-onload/view.json +++ b/testcase/data/twig-form-timing-onload/view.json @@ -286,7 +286,7 @@ 0 ], "script": [ - "\nMolecular formula: \n\n" + "
\nMolecular formula: \n\n
\nSome text insert here: {{ textData }}\n
\n\n" ] } ], @@ -307,12 +307,12 @@ "layers": { "Default layer": { "position": { - "left": 0, - "top": 0 + "left": 50, + "top": 28 }, "size": { - "width": 63, - "height": 12 + "width": 75, + "height": 39 }, "zIndex": 0, "display": true, @@ -425,7 +425,7 @@ "Default layer": { "position": { "left": 0, - "top": 14 + "top": 0 }, "size": { "width": 49, @@ -454,6 +454,14 @@ { "rel": "tpl", "name": "template" + }, + { + "rel": "style", + "name": "styleObject" + }, + { + "rel": "value", + "name": "textData" } ], "actions_in": [ @@ -461,7 +469,16 @@ ], "vars_out": [ { - "jpath": [] + "event": "onFormChanged", + "rel": "form", + "jpath": [], + "name": "formChanged" + }, + { + "event": "onFormSubmitted", + "rel": "form", + "jpath": [], + "name": "formSubmitted" } ], "actions_out": [ @@ -667,12 +684,12 @@ "layers": { "Default layer": { "position": { - "left": 0, - "top": 27 + "left": 1, + "top": 11 }, "size": { "width": 48, - "height": 14 + "height": 16 }, "zIndex": 0, "display": true, @@ -793,12 +810,12 @@ "layers": { "Default layer": { "position": { - "left": 0, - "top": 43 + "left": 1, + "top": 28 }, "size": { "width": 48, - "height": 17 + "height": 9 }, "zIndex": 0, "display": true, @@ -869,6 +886,615 @@ } ], "title": "" + }, + { + "url": "modules/types/client_interaction/code_executor/", + "configuration": { + "sections": {}, + "groups": { + "group": [ + { + "display": [ + [ + "editor", + "buttons" + ] + ], + "execOnLoad": [ + [] + ], + "asyncAwait": [ + [ + "top" + ] + ], + "script": [ + "API.createData('styleObject', {})" + ] + } + ], + "libs": [ + [ + {} + ] + ], + "buttons": [ + [ + { + "name": "button1", + "label": "Execute", + "hide": [], + "disable": [] + } + ] + ] + } + }, + "layers": { + "Default layer": { + "position": { + "left": 1, + "top": 38 + }, + "size": { + "width": 48, + "height": 9 + }, + "zIndex": 0, + "display": true, + "title": "", + "bgColor": [ + 255, + 255, + 255, + 0 + ], + "wrapper": true, + "created": true, + "name": "Default layer" + } + }, + "id": 8, + "vars_in": [ + {} + ], + "actions_in": [ + {} + ], + "vars_out": [ + { + "jpath": [] + } + ], + "actions_out": [ + { + "jpath": [] + } + ], + "toolbar": { + "custom": [ + [ + { + "title": "", + "icon": "", + "action": "", + "position": "begin", + "color": [ + 100, + 100, + 100, + 1 + ] + } + ] + ], + "common": [ + { + "toolbar": [ + [ + "Open Preferences" + ] + ] + } + ] + }, + "css": [ + { + "fontSize": [ + "" + ], + "fontFamily": [ + "" + ] + } + ], + "title": "" + }, + { + "url": "modules/types/edition/object_editor/", + "configuration": { + "sections": {}, + "groups": { + "group": [ + { + "editable": [ + "view" + ], + "expanded": [ + [] + ], + "storeObject": [ + [] + ], + "displayValue": [ + [] + ], + "searchBox": [ + [ + "search" + ] + ], + "sendButton": [ + [] + ], + "output": [ + "new" + ], + "storedObject": [ + "{}" + ] + } + ] + } + }, + "layers": { + "Default layer": { + "position": { + "left": 50, + "top": 0 + }, + "size": { + "width": 37, + "height": 27 + }, + "zIndex": 0, + "display": true, + "title": "On form value changed", + "bgColor": [ + 255, + 255, + 255, + 0 + ], + "wrapper": true, + "created": true, + "name": "Default layer" + } + }, + "id": 9, + "vars_in": [ + { + "rel": "value", + "name": "formChanged" + } + ], + "actions_in": [ + {} + ], + "vars_out": [ + { + "jpath": [] + } + ], + "actions_out": [ + { + "jpath": [] + } + ], + "toolbar": { + "custom": [ + [ + { + "title": "", + "icon": "", + "action": "", + "position": "begin", + "color": [ + 100, + 100, + 100, + 1 + ] + } + ] + ], + "common": [ + { + "toolbar": [ + [ + "Open Preferences" + ] + ] + } + ] + }, + "css": [ + { + "fontSize": [ + "" + ], + "fontFamily": [ + "" + ] + } + ], + "title": "On form value changed" + }, + { + "url": "modules/types/edition/object_editor/", + "configuration": { + "sections": {}, + "groups": { + "group": [ + { + "editable": [ + "view" + ], + "expanded": [ + [] + ], + "storeObject": [ + [] + ], + "displayValue": [ + [] + ], + "searchBox": [ + [ + "search" + ] + ], + "sendButton": [ + [] + ], + "output": [ + "new" + ], + "storedObject": [ + "{}" + ] + } + ] + } + }, + "layers": { + "Default layer": { + "position": { + "left": 88, + "top": 0 + }, + "size": { + "width": 37, + "height": 27 + }, + "zIndex": 0, + "display": true, + "title": "Submitted form value", + "bgColor": [ + 255, + 255, + 255, + 0 + ], + "wrapper": true, + "created": true, + "name": "Default layer" + } + }, + "id": 10, + "vars_in": [ + { + "rel": "value", + "name": "formSubmitted" + } + ], + "actions_in": [ + {} + ], + "vars_out": [ + { + "jpath": [] + } + ], + "actions_out": [ + { + "jpath": [] + } + ], + "toolbar": { + "custom": [ + [ + { + "title": "", + "icon": "", + "action": "", + "position": "begin", + "color": [ + 100, + 100, + 100, + 1 + ] + } + ] + ], + "common": [ + { + "toolbar": [ + [ + "Open Preferences" + ] + ] + } + ] + }, + "css": [ + { + "fontSize": [ + "" + ], + "fontFamily": [ + "" + ] + } + ], + "title": "Submitted form value" + }, + { + "url": "modules/types/client_interaction/code_executor/", + "configuration": { + "sections": {}, + "groups": { + "group": [ + { + "display": [ + [ + "editor", + "buttons" + ] + ], + "execOnLoad": [ + [] + ], + "asyncAwait": [ + [ + "top" + ] + ], + "script": [ + "API.createData('preferences', {mf: 'C6H6'});" + ] + } + ], + "libs": [ + [ + {} + ] + ], + "buttons": [ + [ + { + "name": "button1", + "label": "Execute", + "hide": [], + "disable": [] + } + ] + ] + } + }, + "layers": { + "Default layer": { + "position": { + "left": 1, + "top": 48 + }, + "size": { + "width": 48, + "height": 9 + }, + "zIndex": 0, + "display": true, + "title": "", + "bgColor": [ + 255, + 255, + 255, + 0 + ], + "wrapper": true, + "created": true, + "name": "Default layer" + } + }, + "id": 11, + "vars_in": [ + {} + ], + "actions_in": [ + {} + ], + "vars_out": [ + { + "jpath": [] + } + ], + "actions_out": [ + { + "jpath": [] + } + ], + "toolbar": { + "custom": [ + [ + { + "title": "", + "icon": "", + "action": "", + "position": "begin", + "color": [ + 100, + 100, + 100, + 1 + ] + } + ] + ], + "common": [ + { + "toolbar": [ + [ + "Open Preferences" + ] + ] + } + ] + }, + "css": [ + { + "fontSize": [ + "" + ], + "fontFamily": [ + "" + ] + } + ], + "title": "" + }, + { + "url": "modules/types/client_interaction/code_executor/", + "configuration": { + "sections": {}, + "groups": { + "group": [ + { + "display": [ + [ + "editor", + "buttons" + ] + ], + "execOnLoad": [ + [] + ], + "asyncAwait": [ + [ + "top" + ] + ], + "script": [ + "API.createData('textData', 'Hello world');" + ] + } + ], + "libs": [ + [ + {} + ] + ], + "buttons": [ + [ + { + "name": "button1", + "label": "Execute", + "hide": [], + "disable": [] + } + ] + ] + } + }, + "layers": { + "Default layer": { + "position": { + "left": 1, + "top": 58 + }, + "size": { + "width": 48, + "height": 9 + }, + "zIndex": 0, + "display": true, + "title": "", + "bgColor": [ + 255, + 255, + 255, + 0 + ], + "wrapper": true, + "created": true, + "name": "Default layer" + } + }, + "id": 12, + "vars_in": [ + {} + ], + "actions_in": [ + {} + ], + "vars_out": [ + { + "jpath": [] + } + ], + "actions_out": [ + { + "jpath": [] + } + ], + "toolbar": { + "custom": [ + [ + { + "title": "", + "icon": "", + "action": "", + "position": "begin", + "color": [ + 100, + 100, + 100, + 1 + ] + } + ] + ], + "common": [ + { + "toolbar": [ + [ + "Open Preferences" + ] + ] + } + ] + }, + "css": [ + { + "fontSize": [ + "" + ], + "fontFamily": [ + "" + ] + } + ], + "title": "" } ], "variables": [