diff --git a/grails-app/assets/javascripts/forms-knockout-bindings.js b/grails-app/assets/javascripts/forms-knockout-bindings.js index 29ac7aee..06b2b2fe 100644 --- a/grails-app/assets/javascripts/forms-knockout-bindings.js +++ b/grails-app/assets/javascripts/forms-knockout-bindings.js @@ -1179,9 +1179,7 @@ }; ko.bindingHandlers['triggerPrePopulate'] = { - 'update': function (element, valueAccessor, allBindings, viewModel, bindingContext) { - - + 'init': function (element, valueAccessor, allBindings, viewModel, bindingContext) { var dataModelItem = valueAccessor(); var behaviours = dataModelItem.get('behaviour'); for (var i = 0; i < behaviours.length; i++) { @@ -1206,8 +1204,15 @@ } } var dependencyTracker = ko.computed(function () { - dataModelItem(); // register dependency on the observable. + var initialised = (dataModelItem.context.lifecycleState && dataModelItem.context.lifecycleState() == 'initialised'); + dataLoader.prepop(config).done(function (data) { + + if (config.waitForInitialisation && !initialised) { + console.log("Not applying any updates during initialisation") + return; + } + data = data || {}; var configTarget = config.target; var target; diff --git a/grails-app/assets/javascripts/forms.js b/grails-app/assets/javascripts/forms.js index 2c395a3a..acbbbd2f 100644 --- a/grails-app/assets/javascripts/forms.js +++ b/grails-app/assets/javascripts/forms.js @@ -1024,7 +1024,7 @@ function orEmptyArray(v) { else { self(data); } - + return constraintsInititaliser; } }; @@ -1066,6 +1066,7 @@ function orEmptyArray(v) { self.addRow = function (data) { var newItem = self.newItem(data, self.rowCount()); self.push(newItem); + return newItem.loadData(data || {}); }; self.newItem = function (data, index) { var itemDataModel = _.indexBy(dataModel[listName].columns, 'name'); @@ -1155,6 +1156,7 @@ function orEmptyArray(v) { }; parent['load' + listName] = function (data, append) { + var initialisers = []; if (!append) { self([]); } @@ -1163,9 +1165,10 @@ function orEmptyArray(v) { } else { _.each(data, function (row, i) { - self.push(self.newItem(row, i)); + initialisers = initialisers.concat(self.addRow(row)); }); } + return initialisers; }; }; @@ -1560,12 +1563,16 @@ function orEmptyArray(v) { }; self.initialise = function (outputData) { + var deferred = $.Deferred(); + self.loadOrPrepop(outputData).done(function (data) { + var initialisers = self.loadData(data); - return self.loadOrPrepop(outputData).done(function (data) { - self.loadData(data); - self.transients.dummy.notifySubscribers(); + $.when.apply($, initialisers).then(function () { + deferred.resolve(); + self.transients.dummy.notifySubscribers(); + }); }); - + return deferred; }; diff --git a/grails-app/taglib/au/org/ala/ecodata/forms/ModelJSTagLib.groovy b/grails-app/taglib/au/org/ala/ecodata/forms/ModelJSTagLib.groovy index 3e8c341e..86e83ee3 100644 --- a/grails-app/taglib/au/org/ala/ecodata/forms/ModelJSTagLib.groovy +++ b/grails-app/taglib/au/org/ala/ecodata/forms/ModelJSTagLib.groovy @@ -200,7 +200,7 @@ class ModelJSTagLib { void renderLoad(List items, JSModelRenderContext ctx) { ctx.out << "self.loadData = function(data) {\n" - + out << INDENT * 1 << "var initialisers = [];\n" JSModelRenderContext child = ctx.createChildContext() Map attrs = ctx.attrs @@ -209,7 +209,7 @@ class ModelJSTagLib { child.dataModel = mod if (mod.dataType == 'list') { - out << INDENT * 1 << "self.load${mod.name}(data.${mod.name});\n" + out << INDENT * 1 << "initialisers = initialisers.concat(self.load${mod.name}(data.${mod.name}));\n" loadColumnTotals out, attrs, mod } else if (mod.dataType == 'matrix') { out << INDENT * 1 << "self.load${mod.name.capitalize()}(data.${mod.name});\n" @@ -217,7 +217,7 @@ class ModelJSTagLib { renderInitialiser(child) } } - + out << INDENT * 1 << "return initialisers;\n" ctx.out << "};\n" } @@ -266,7 +266,7 @@ class ModelJSTagLib { out << INDENT*4 << "${ctx.propertyPath}['${mod.name}'](ecodata.forms.orDefault(data['${mod.name}'], '${attrs.user.displayName}'));\n" } else { if (requiresMetadataExtender(mod)) { - out << INDENT*4 << "${ctx.propertyPath}['${mod.name}'].load(${value});\n" + out << INDENT*4 << "initialisers.push(${ctx.propertyPath}['${mod.name}'].load(${value}));\n" } else { out << INDENT*4 << "${ctx.propertyPath}['${mod.name}'](${value});\n" @@ -531,8 +531,6 @@ class ModelJSTagLib { } renderLoad(ctx.dataModel.columns, childCtx) - out << INDENT*4 << "self.loadData(data || {});\n" - out << INDENT*2 << "};\n" } @@ -748,13 +746,13 @@ class ModelJSTagLib { boolean userAddedRows = Boolean.valueOf(viewModel?.userAddedRows) def defaultRows = [] model.defaultRows?.eachWithIndex { row, i -> - defaultRows << INDENT*5 + "${ctx.propertyPath}.${model.name}.addRow(${row.toString()});" + defaultRows << INDENT*5 + "rowInitalisers.push(${ctx.propertyPath}.${model.name}.addRow(${row.toString()}));" } def insertDefaultModel = defaultRows.join('\n') // If there are no default rows, insert a single blank row and make it available for editing. if (attrs.edit && model.defaultRows == null) { - insertDefaultModel = "${ctx.propertyPath}.${model.name}.addRow();" + insertDefaultModel = "rowInitalisers.push(${ctx.propertyPath}.${model.name}.addRow());" } out << """var context = _.extend({}, context, {parent:self, listName:'${model.name}'});""" @@ -762,7 +760,9 @@ class ModelJSTagLib { observableArray(ctx, [extender], false) out << """ ${ctx.propertyPath}.${model.name}.loadDefaults = function() { + var rowInitalisers = []; ${insertDefaultModel} + return rowInitialisers; }; """ diff --git a/src/test/groovy/au/org/ala/ecodata/forms/ModelJSTagLibSpec.groovy b/src/test/groovy/au/org/ala/ecodata/forms/ModelJSTagLibSpec.groovy index 2bee6ada..4eb3c190 100644 --- a/src/test/groovy/au/org/ala/ecodata/forms/ModelJSTagLibSpec.groovy +++ b/src/test/groovy/au/org/ala/ecodata/forms/ModelJSTagLibSpec.groovy @@ -243,7 +243,7 @@ class ModelJSTagLibSpec extends Specification implements TagLibUnitTest