From 789a9434c12925ed72914713f99aad90952c2dfd Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 3 Aug 2018 10:22:29 +1000 Subject: [PATCH] fixes property rebinding with variants and fixes more validation flow --- .../components/content/edit.controller.js | 8 +- .../services/contenteditinghelper.service.js | 91 ++++++++++++------- 2 files changed, 65 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index affe1bb370..90d9bc278f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -182,9 +182,8 @@ //in one particular special case, after we've created a new item we redirect back to the edit // route but there might be server validation errors in the collection which we need to display - // after the redirect, so we will bind all subscriptions which will show the server validation errors - // if there are any and then clear them so the collection no longer persists them. - serverValidationManager.notifyAndClearAllSubscriptions(); + // after the redirect, so we will bind all subscriptions which will show the server validation errors. + serverValidationManager.notify(); if (!infiniteMode) { syncTreeNode($scope.content, data.path, true); @@ -666,6 +665,9 @@ for (var e in evts) { eventsService.unsubscribe(evts[e]); } + //since we are not notifying and clearing server validation messages when they are received due to how the variant + //switching works, we need to ensure they are cleared when this editor is destroyed + serverValidationManager.clear(); }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js index 567657f518..2c227bcd13 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js @@ -289,7 +289,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica * @function * * @description - * Returns all propertes contained for the content item (since the normal model has properties contained inside of tabs) + * Returns all propertes contained for the tabbed content item */ getAllProps: function (content) { var allProps = []; @@ -415,26 +415,17 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica * @function * * @description - * re-binds all changed property values to the origContent object from the savedContent object and returns an array of changed properties. + * Re-binds all changed property values to the origContent object from the savedContent object and returns an array of changed properties. + * This re-binds both normal object property values along with content property values and works for content, media and members. + * For variant content, this detects if the object contains the 'variants' property (i.e. for content) and re-binds all variant content properties. + * This returns the list of changed content properties (does not include standard object property changes). */ reBindChangedProperties: function (origContent, savedContent) { - var changed = []; - - //get a list of properties since they are contained in tabs - var allOrigProps = this.getAllProps(origContent); - var allNewProps = this.getAllProps(savedContent); - - function getNewProp(alias) { - return _.find(allNewProps, function (item) { - return item.alias === alias; - }); - } - //a method to ignore built-in prop changes var shouldIgnore = function(propName) { return _.some([ - "tabs", + "variants", "notifications", "ModelState", "tabs", @@ -468,24 +459,59 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica } } - //check for changed properties of the content - for (var p in allOrigProps) { - var newProp = getNewProp(allOrigProps[p].alias); - if (newProp && !_.isEqual(allOrigProps[p].value, newProp.value)) { + //Now re-bind content properties. Since content has variants and media/members doesn't, + //we'll detect the variants property for content to distinguish if it's content vs media/members. - //they have changed so set the origContent prop to the new one - var origVal = allOrigProps[p].value; - allOrigProps[p].value = newProp.value; + var origVariants = []; + var savedVariants = []; + if (origContent.variants) { + //it's contnet so assign the variants as they exist + origVariants = origContent.variants; + savedVariants = savedContent.variants; + } + else { + //it's media/member, so just add the object as-is to the variants collection + origVariants.push(origContent); + savedVariants.push(savedContent); + } - //instead of having a property editor $watch their expression to check if it has - // been updated, instead we'll check for the existence of a special method on their model - // and just call it. - if (angular.isFunction(allOrigProps[p].onValueChanged)) { - //send the newVal + oldVal - allOrigProps[p].onValueChanged(allOrigProps[p].value, origVal); + var changed = []; + + function getNewProp(alias, allNewProps) { + return _.find(allNewProps, function (item) { + return item.alias === alias; + }); + } + + //loop through each variant (i.e. tabbed content) + for (var j = 0; j < origVariants.length; j++) { + + var origVariant = origVariants[j]; + var savedVariant = savedVariants[j]; + + //get a list of properties since they are contained in tabs + var allOrigProps = this.getAllProps(origVariant); + var allNewProps = this.getAllProps(savedVariant); + + //check for changed properties of the content + for (var p in allOrigProps) { + var newProp = getNewProp(allOrigProps[p].alias, allOrigProps); + if (newProp && !_.isEqual(allOrigProps[p].value, newProp.value)) { + + //they have changed so set the origContent prop to the new one + var origVal = allOrigProps[p].value; + allOrigProps[p].value = newProp.value; + + //instead of having a property editor $watch their expression to check if it has + // been updated, instead we'll check for the existence of a special method on their model + // and just call it. + if (angular.isFunction(allOrigProps[p].onValueChanged)) { + //send the newVal + oldVal + allOrigProps[p].onValueChanged(allOrigProps[p].value, origVal); + } + + changed.push(allOrigProps[p]); } - - changed.push(allOrigProps[p]); } } @@ -530,7 +556,10 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica args.rebindCallback(); } - serverValidationManager.notifyAndClearAllSubscriptions(); + //notify all validators (don't clear the server validations though since we need to maintain their state because of + // how the variant switcher works in content). server validation state is always cleared when an editor first loads + // and in theory when an editor is destroyed. + serverValidationManager.notify(); } //indicates we've handled the server result