From e23e490b99e295ef5b61fb5fa81f6ff68cb4d69b Mon Sep 17 00:00:00 2001 From: chrisala Date: Thu, 4 Jan 2024 14:49:34 +1100 Subject: [PATCH 1/3] Only pre-pop fields that exist in the result #219 --- .../javascripts/forms-knockout-bindings.js | 23 ++++++++++++------- .../example_models/behavioursExample.json | 11 +-------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/grails-app/assets/javascripts/forms-knockout-bindings.js b/grails-app/assets/javascripts/forms-knockout-bindings.js index 5707d60..8cf8993 100644 --- a/grails-app/assets/javascripts/forms-knockout-bindings.js +++ b/grails-app/assets/javascripts/forms-knockout-bindings.js @@ -1207,16 +1207,23 @@ if (!target) { throw "Unable to locate target for pre-population: "+target; } - if (_.isFunction(target.loadData)) { - target.loadData(data); - } else if (_.isFunction(target.load)) { - target.load(data); - } else if (ko.isObservable(target)) { - target(data); - } else { - console.log("Warning: target for pre-populate is invalid"); + target = target.data || target; + for (var prop in data) { + if (target.hasOwnProperty(prop)) { + var propTarget = target[prop]; + if (_.isFunction(propTarget.loadData)) { + propTarget.loadData(data[prop]); + } else if (_.isFunction(propTarget.load)) { + propTarget.load(data[prop]); + } else if (ko.isObservable(propTarget)) { + propTarget(data[prop]); + } else { + console.log("Warning: target for pre-populate is invalid"); + } + } } + }); // This is a computed rather than a pureComputed as it has a side effect. }); } diff --git a/grails-app/conf/example_models/behavioursExample.json b/grails-app/conf/example_models/behavioursExample.json index d588fa5..ec48ab3 100644 --- a/grails-app/conf/example_models/behavioursExample.json +++ b/grails-app/conf/example_models/behavioursExample.json @@ -45,11 +45,6 @@ "name": "param", "type": "computed", "expression": "item5" - }, - { - "name": "item5", - "type": "computed", - "expression": "item5" } ] }, @@ -57,10 +52,6 @@ { "source-path": "param", "target": "item6" - }, - { - "source-path": "item5", - "target": "item5" } ], "target": "$data" @@ -119,7 +110,7 @@ "items": [ { "type": "literal", - "source": "Note for this example, data entered into item5 will trigger a pre-pop call and be mapped back to item5 and item6. Note that the target of the pre-pop is $data which is the current binding context (or the root object in this case). A current limitation is the load method is used, which means if the pre-pop result does not contain keys for all data in the target object, the data for missing fields will be set to undefined. A planned enhancement is to only replace data where keys in the pre-pop data exist." + "source": "Note for this example, data entered into item5 will trigger a pre-pop call and be mapped back to item6. Note that the target of the pre-pop is $data which is the current binding context (or the root object in this case). A current limitation is the load method is used for all keys in the returned data, which means if the data is nested and the pre-pop result does not contain keys for all nested data in the nested target object, the data for missing fields will be set to undefined." } ] } From e3582e7061d09e0ac2fb114659a2652a970ee864 Mon Sep 17 00:00:00 2001 From: chrisala Date: Thu, 4 Jan 2024 16:07:11 +1100 Subject: [PATCH 2/3] More pre-pop target configuration options #219 --- .../javascripts/forms-knockout-bindings.js | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/grails-app/assets/javascripts/forms-knockout-bindings.js b/grails-app/assets/javascripts/forms-knockout-bindings.js index 8cf8993..c7609c1 100644 --- a/grails-app/assets/javascripts/forms-knockout-bindings.js +++ b/grails-app/assets/javascripts/forms-knockout-bindings.js @@ -1193,37 +1193,52 @@ var dataLoader = new ecodata.forms.dataLoader(dataLoaderContext, dataModelItem.config); + function doLoad(propTarget, value) { + + if (_.isFunction(propTarget.loadData)) { + propTarget.loadData(value); + } else if (_.isFunction(propTarget.load)) { + propTarget.load(value); + } else if (ko.isObservable(propTarget)) { + propTarget(value); + } else { + console.log("Warning: target for pre-populate is invalid"); + } + } var dependencyTracker = ko.computed(function () { dataModelItem(); // register dependency on the observable. dataLoader.prepop(config).done(function (data) { data = data || {}; - var target = config.target; - if (!target) { + var configTarget = config.target; + var target; + if (!configTarget) { target = viewModel; } else { - target = dataModelItem.findNearestByName(target, bindingContext); + target = dataModelItem.findNearestByName(configTarget.name, bindingContext); } if (!target) { throw "Unable to locate target for pre-population: "+target; } - target = target.data || target; - for (var prop in data) { - if (target.hasOwnProperty(prop)) { - var propTarget = target[prop]; - if (_.isFunction(propTarget.loadData)) { - propTarget.loadData(data[prop]); - } else if (_.isFunction(propTarget.load)) { - propTarget.load(data[prop]); - } else if (ko.isObservable(propTarget)) { - propTarget(data[prop]); - } else { - console.log("Warning: target for pre-populate is invalid"); + if (configTarget.type == "singleValue") { + // This needs to be done to load data into the feature data type due to the awkward + // way the loadData method uses the feature id from the reporting site and the + // direct observable accepts geojson. + target(data); + } + else if (configTarget.type = "singleLoad") { + loadData(target, data); + } + else { + target = target.data || target; + for (var prop in data) { + if (target.hasOwnProperty(prop)) { + var propTarget = target[prop]; + doLoad(propTarget, data[prop]); } } } - }); // This is a computed rather than a pureComputed as it has a side effect. }); } From 76a367ef35b14e1b8b5d4033868bae87f63ddd96 Mon Sep 17 00:00:00 2001 From: chrisala Date: Fri, 5 Jan 2024 08:59:53 +1100 Subject: [PATCH 3/3] Fixed test #219 --- grails-app/assets/javascripts/forms-knockout-bindings.js | 4 ++-- src/test/js/spec/TriggerPrePopulateBindingSpec.js | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/grails-app/assets/javascripts/forms-knockout-bindings.js b/grails-app/assets/javascripts/forms-knockout-bindings.js index c7609c1..29ac7ae 100644 --- a/grails-app/assets/javascripts/forms-knockout-bindings.js +++ b/grails-app/assets/javascripts/forms-knockout-bindings.js @@ -1226,8 +1226,8 @@ // direct observable accepts geojson. target(data); } - else if (configTarget.type = "singleLoad") { - loadData(target, data); + else if (configTarget.type == "singleLoad") { + doLoad(target, data); } else { target = target.data || target; diff --git a/src/test/js/spec/TriggerPrePopulateBindingSpec.js b/src/test/js/spec/TriggerPrePopulateBindingSpec.js index b328d50..ca9d196 100644 --- a/src/test/js/spec/TriggerPrePopulateBindingSpec.js +++ b/src/test/js/spec/TriggerPrePopulateBindingSpec.js @@ -25,7 +25,9 @@ describe("triggerPrePopulate binding handler Spec", function () { source: { "context-path":"test" }, - target: "item2" + target: { + name:"item2" + } } }