diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js
index a34c4aa0cc..181d204336 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js
@@ -288,7 +288,7 @@ function valPropertyMsg(serverValidationManager, localizationService, angularHel
"",
serverValidationManagerCallback,
currentSegment,
- { matchPrefix: true } // match property validation path prefix
+ { matchType: "suffix" } // match property validation path prefix
));
}
@@ -298,9 +298,7 @@ function valPropertyMsg(serverValidationManager, localizationService, angularHel
//when the scope is disposed we need to unsubscribe
scope.$on('$destroy', function () {
stopWatch();
- for (var u in unsubscribe) {
- unsubscribe[u]();
- }
+ unsubscribe.forEach(u => u());
});
onInit();
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js
index b9b9b98174..ea6087d4e9 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js
@@ -13,14 +13,14 @@ function valServer(serverValidationManager) {
link: function (scope, element, attr, ctrls) {
var modelCtrl = ctrls[0];
- var umbPropCtrl = ctrls.length > 1 ? ctrls[1] : null;
+ var umbPropCtrl = ctrls[1];
if (!umbPropCtrl) {
//we cannot proceed, this validator will be disabled
return;
}
// optional reference to the varaint-content-controller, needed to avoid validation when the field is invariant on non-default languages.
- var umbVariantCtrl = ctrls.length > 2 ? ctrls[2] : null;
+ var umbVariantCtrl = ctrls[2];
var currentProperty = umbPropCtrl.property;
var currentCulture = currentProperty.culture;
@@ -121,9 +121,7 @@ function valServer(serverValidationManager) {
scope.$on('$destroy', function () {
stopWatch();
- for (var u in unsubscribe) {
- unsubscribe[u]();
- }
+ unsubscribe.forEach(u => u());
});
}
};
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valservermatch.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valservermatch.directive.js
new file mode 100644
index 0000000000..766f3f6755
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valservermatch.directive.js
@@ -0,0 +1,89 @@
+
+function valServerMatch(serverValidationManager) {
+ return {
+ require: ['form', '^^umbProperty', '?^^umbVariantContent'],
+ restrict: "A",
+ scope: {
+ valServerMatch: "="
+ },
+ link: function (scope, element, attr, ctrls) {
+
+ var formCtrl = ctrls[0];
+ var umbPropCtrl = ctrls[1];
+ if (!umbPropCtrl) {
+ //we cannot proceed, this validator will be disabled
+ return;
+ }
+
+ // optional reference to the varaint-content-controller, needed to avoid validation when the field is invariant on non-default languages.
+ var umbVariantCtrl = ctrls[2];
+
+ var currentProperty = umbPropCtrl.property;
+ var currentCulture = currentProperty.culture;
+ var currentSegment = currentProperty.segment;
+
+ if (umbVariantCtrl) {
+ //if we are inside of an umbVariantContent directive
+
+ var currentVariant = umbVariantCtrl.editor.content;
+
+ // Lets check if we have variants and we are on the default language then ...
+ if (umbVariantCtrl.content.variants.length > 1 && (!currentVariant.language || !currentVariant.language.isDefault) && !currentCulture && !currentSegment && !currentProperty.unlockInvariantValue) {
+ //This property is locked cause its a invariant property shown on a non-default language.
+ //Therefor do not validate this field.
+ return;
+ }
+ }
+
+ // if we have reached this part, and there is no culture, then lets fallback to invariant. To get the validation feedback for invariant language.
+ currentCulture = currentCulture || "invariant";
+
+ var unsubscribe = [];
+
+ //subscribe to the server validation changes
+ function serverValidationManagerCallback(isValid, propertyErrors, allErrors) {
+ if (!isValid) {
+ formCtrl.$setValidity('valServerMatch', false, formCtrl);
+ }
+ else {
+ formCtrl.$setValidity('valServerMatch', true, formCtrl);
+ }
+ }
+
+ if (Utilities.isObject(scope.valServerMatch)) {
+ var allowedKeys = ["contains", "prefix", "suffix"];
+ Object.keys(scope.valServerMatch).forEach(k => {
+ if (allowedKeys.indexOf(k) === -1) {
+ throw "valServerMatch dictionary keys must be one of " + allowedKeys.join();
+ }
+
+ unsubscribe.push(serverValidationManager.subscribe(
+ scope.valServerMatch[k],
+ currentCulture,
+ "",
+ serverValidationManagerCallback,
+ currentSegment,
+ { matchType: k } // specify the match type
+ ));
+
+ });
+ }
+ else if (Utilities.isString(scope.valServerMatch)) {
+ unsubscribe.push(serverValidationManager.subscribe(
+ scope.valServerMatch,
+ currentCulture,
+ "",
+ serverValidationManagerCallback,
+ currentSegment));
+ }
+ else {
+ throw "valServerMatch value must be a string or a dictionary";
+ }
+
+ scope.$on('$destroy', function () {
+ unsubscribe.forEach(u => u());
+ });
+ }
+ };
+}
+angular.module('umbraco.directives.validation').directive("valServerMatch", valServerMatch);
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js
index 4cd2720216..9259e4bf64 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js
@@ -129,9 +129,9 @@
var prop = tab.properties[p];
// Watch value of property since this is the only value we want to keep synced.
- // Do notice that it is not performing a deep watch, meaning that we are only watching primatives and changes directly to the object of property-value.
- // But we like to sync non-primative values as well! Yes, and this does happen, just not through this code, but through the nature of JavaScript.
- // Non-primative values act as references to the same data and are therefor synced.
+ // Do notice that it is not performing a deep watch, meaning that we are only watching primitive and changes directly to the object of property-value.
+ // But we like to sync non-primitive values as well! Yes, and this does happen, just not through this code, but through the nature of JavaScript.
+ // Non-primitive values act as references to the same data and are therefor synced.
blockObject.__watchers.push(isolatedScope.$watch("blockObjects._" + blockObject.key + "." + field + ".variants[0].tabs[" + t + "].properties[" + p + "].value", watcherCreator(blockObject, prop)));
// We also like to watch our data model to be able to capture changes coming from other places.
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js
index a62b632d38..daded4d9a9 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js
@@ -63,8 +63,20 @@ angular.module("umbraco")
}
}
- vm.close = function() {
+ vm.close = function () {
if (vm.model && vm.model.close) {
+ // TODO: At this stage there could very well have been server errors that have been cleared
+ // but if we 'close' we are basically cancelling the value changes which means we'd want to cancel
+ // all of the server errors just cleared. It would be possible to do that but also quite annoying.
+ // The rudimentary way would be to:
+ // * Track all cleared server errors here by subscribing to the prefix validation of controls contained here
+ // * If this is closed, re-add all of those server validation errors
+ // A more robust way to do this would be to:
+ // * Add functionality to the serverValidationManager whereby we can remove validation errors and it will
+ // maintain a copy of the original errors
+ // * It would have a 'commit' method to commit the removed errors - which we would call in the formHelper.submitForm when it's successful
+ // * It would have a 'rollback' method to reset the removed errors - which we would call here
+
// TODO: check if content/settings has changed and ask user if they are sure.
vm.model.close(vm.model);
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.html
index 91c8468d2d..90d0f4bcb4 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.html
@@ -1,7 +1,10 @@
-
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/block-editor-service.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/block-editor-service.spec.js
index e0cd2d0c93..7f69f0594e 100644
--- a/src/Umbraco.Web.UI.Client/test/unit/common/services/block-editor-service.spec.js
+++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/block-editor-service.spec.js
@@ -119,7 +119,7 @@
});
- it('getBlockObject syncs primative values', function (done) {
+ it('getBlockObject syncs primitive values', function (done) {
var propertyModel = angular.copy(propertyModelMock);