Fixes block list editor to correctly re-sync it's view model after persisting

This commit is contained in:
Shannon
2020-07-14 09:43:10 +10:00
committed by Warren Buckley
parent 4e8feae35b
commit f759ab4d36
2 changed files with 51 additions and 24 deletions

View File

@@ -256,13 +256,34 @@
this.isolatedScope.blockObjects = {};
this.__watchers.push(this.isolatedScope.$on("$destroy", this.destroy.bind(this)));
this.__watchers.push(propertyEditorScope.$on("postFormSubmitting", this.sync.bind(this)));
};
BlockEditorModelObject.prototype = {
update: function (propertyModelValue, propertyEditorScope) {
// clear watchers
this.__watchers.forEach(w => { w(); });
delete this.__watchers;
// clear block objects
for (const key in this.isolatedScope.blockObjects) {
this.destroyBlockObject(this.isolatedScope.blockObjects[key]);
}
this.isolatedScope.blockObjects = {};
// update our values
this.value = propertyModelValue;
this.value.layout = this.value.layout || {};
this.value.data = this.value.data || [];
// re-create the watchers
this.__watchers = [];
this.__watchers.push(this.isolatedScope.$on("$destroy", this.destroy.bind(this)));
this.__watchers.push(propertyEditorScope.$on("postFormSubmitting", this.sync.bind(this)));
},
/**
* @ngdoc method
* @name getBlockConfiguration
@@ -279,8 +300,8 @@
* @ngdoc method
* @name load
* @methodOf umbraco.services.blockEditorModelObject
* @description Load the scaffolding models for the given configuration, these are needed to provide usefull models for each block.
* @param {Object} blockObject BlockObject to recive data values from.
* @description Load the scaffolding models for the given configuration, these are needed to provide useful models for each block.
* @param {Object} blockObject BlockObject to receive data values from.
* @returns {Promise} A Promise object which resolves when all scaffold models are loaded.
*/
load: function() {
@@ -295,7 +316,7 @@
}
});
// removing dublicates.
// removing duplicates.
scaffoldKeys = scaffoldKeys.filter((value, index, self) => self.indexOf(value) === index);
scaffoldKeys.forEach((contentTypeKey => {
@@ -472,7 +493,7 @@
}
}
blockObject.retriveValuesFrom = function(content, settings) {
blockObject.retrieveValuesFrom = function(content, settings) {
if (this.content !== null) {
mapElementValues(content, this.content);
}
@@ -482,7 +503,7 @@
}
blockObject.sync = function() {
blockObject.sync = function () {
if (this.content !== null) {
mapToPropertyModel(this.content, this.data);
}
@@ -499,13 +520,14 @@
addWatchers(blockObject, this.isolatedScope);
addWatchers(blockObject, this.isolatedScope, true);
blockObject.destroy = function() {
blockObject.destroy = function () {
// remove property value watchers:
this.__watchers.forEach(w => { w(); });
delete this.__watchers;
// help carbage collector:
delete this.config;
delete this.layout;
delete this.data;
delete this.content;
@@ -513,9 +535,12 @@
// remove model from isolatedScope.
delete this.__scope.blockObjects["_" + this.key];
// NOTE: It seems like we should call this.__scope.$destroy(); since that is the only way to remove a scope from it's parent,
// however that is not the case since __scope is actually this.isolatedScope which gets cleaned up when the outer scope is
// destroyed. If we do that here it breaks the scope chain and validation.
delete this.__scope;
// removes this method, making it unposible to destroy again.
// removes this method, making it impossible to destroy again.
delete this.destroy;
// lets remove the key to make things blow up if this is still referenced:
@@ -621,8 +646,6 @@
},
/**
* @ngdoc method
* @name sync
@@ -636,6 +659,7 @@
},
// private
// TODO: Then this can just be a method in the outer scope
_createDataEntry: function(elementTypeKey) {
var content = {
contentTypeKey: elementTypeKey,
@@ -645,6 +669,7 @@
return content.udi;
},
// private
// TODO: Then this can just be a method in the outer scope
_getDataByUdi: function(udi) {
return this.value.data.find(entry => entry.udi === udi) || null;
},

View File

@@ -53,8 +53,8 @@
}
vm.supportCopy = clipboardService.isSupported();
vm.layout = [];// The layout object specific to this Block Editor, will be a direct reference from Property Model.
vm.availableBlockTypes = [];// Available block entries of this property editor.
vm.layout = []; // The layout object specific to this Block Editor, will be a direct reference from Property Model.
vm.availableBlockTypes = []; // Available block entries of this property editor.
var labels = {};
vm.labels = labels;
@@ -63,12 +63,12 @@
labels.content_createEmpty = data[1];
});
vm.$onInit = function() {
// set the onValueChanged callback, this will tell us if the block list model changed on the server
// once the data is submitted. If so we need to re-initialize
vm.model.onValueChanged = onServerValueChanged;
inlineEditing = vm.model.config.useInlineEditingAsDefault;
liveEditing = vm.model.config.useLiveEditing;
@@ -121,8 +121,12 @@
}
};
// Called when we save the value, the server may return an updated data and our value is re-synced
// we need to deal with that here so that our model values are all in sync so we basically re-initialize.
function onServerValueChanged(newVal, oldVal) {
modelObject.update(newVal, $scope);
onLoaded();
}
function setDirty() {
if (vm.propertyForm) {
@@ -137,7 +141,7 @@
// Append the blockObjects to our layout.
vm.layout.forEach(entry => {
// $block must have the data property to be a valid BlockObject, if not its concidered as a destroyed blockObject.
// $block must have the data property to be a valid BlockObject, if not its considered as a destroyed blockObject.
if (entry.$block === undefined || entry.$block === null || entry.$block.data === undefined) {
var block = getBlockObject(entry);
@@ -176,7 +180,7 @@
block.hideContentInOverlay = block.config.forceHideContentEditorInOverlay === true || inlineEditing === true;
block.showSettings = block.config.settingsElementTypeKey != null;
block.showCopy = vm.supportCopy && block.config.contentTypeKey != null;// if we have content, otherwise it dosnt make sense to copy.
block.showCopy = vm.supportCopy && block.config.contentTypeKey != null;// if we have content, otherwise it doesn't make sense to copy.
return block;
}
@@ -211,8 +215,6 @@
}
function deleteBlock(block) {
var layoutIndex = vm.layout.findIndex(entry => entry.udi === block.content.udi);
@@ -269,7 +271,7 @@
if (liveEditing === false) {
// transfer values when submitting in none-liveediting mode.
blockObject.retriveValuesFrom(blockEditorModel.content, blockEditorModel.settings);
blockObject.retrieveValuesFrom(blockEditorModel.content, blockEditorModel.settings);
}
blockObject.active = false;
@@ -279,7 +281,7 @@
if (liveEditing === true) {
// revert values when closing in liveediting mode.
blockObject.retriveValuesFrom(blockContentClone, blockSettingsClone);
blockObject.retrieveValuesFrom(blockContentClone, blockSettingsClone);
}
if (wasNotActiveBefore === true) {