diff --git a/grails-app/assets/javascripts/forms-knockout-bindings.js b/grails-app/assets/javascripts/forms-knockout-bindings.js index 5707d60..29ac7ae 100644 --- a/grails-app/assets/javascripts/forms-knockout-bindings.js +++ b/grails-app/assets/javascripts/forms-knockout-bindings.js @@ -1193,28 +1193,50 @@ 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; } - if (_.isFunction(target.loadData)) { - target.loadData(data); - } else if (_.isFunction(target.load)) { - target.load(data); - } else if (ko.isObservable(target)) { + 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 { - console.log("Warning: target for pre-populate is invalid"); + } + else if (configTarget.type == "singleLoad") { + doLoad(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. 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." } ] } 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" + } } }