enhances valServerMatch to be more flexible and allow for different validation keys which we can then use for matching on settings or content and have different styles for validators
This commit is contained in:
@@ -1,5 +1,17 @@
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:valServerMatch
|
||||
* @restrict A
|
||||
* @description A custom validator applied to a form/ng-form within an umbProperty that validates server side validation data
|
||||
* contained within the serverValidationManager. The data can be matched on "exact", "prefix", "suffix" or "contains" matches against
|
||||
* a property validation key. The attribute value can be in multiple value types:
|
||||
* - STRING = The property validation key to have an exact match on. If matched, then the form will have a valServerMatch validator applied.
|
||||
* - OBJECT = A dictionary where the key is the match type: "contains", "prefix", "suffix" and the value is either:
|
||||
* - ARRAY = A list of property validation keys to match on. If any are matched then the form will have a valServerMatch validator applied.
|
||||
* - OBJECT = A dictionary where the key is the validator error name applied to the form and the value is the STRING of the property validation key to match on
|
||||
**/
|
||||
function valServerMatch(serverValidationManager) {
|
||||
|
||||
return {
|
||||
require: ['form', '^^umbProperty', '?^^umbVariantContent'],
|
||||
restrict: "A",
|
||||
@@ -40,48 +52,63 @@ function valServerMatch(serverValidationManager) {
|
||||
|
||||
var unsubscribe = [];
|
||||
|
||||
//subscribe to the server validation changes
|
||||
function serverValidationManagerCallback(isValid, propertyErrors, allErrors) {
|
||||
if (!isValid) {
|
||||
formCtrl.$setValidity('valServerMatch', false);
|
||||
}
|
||||
else {
|
||||
formCtrl.$setValidity('valServerMatch', true);
|
||||
function bindCallback(validationKey, matchVal, matchType) {
|
||||
|
||||
if (Utilities.isString(matchVal)) {
|
||||
matchVal = [matchVal]; // normalize to an array since the value can also natively be an array
|
||||
}
|
||||
|
||||
// match for each string in the array
|
||||
matchVal.forEach(m => {
|
||||
unsubscribe.push(serverValidationManager.subscribe(
|
||||
m,
|
||||
currentCulture,
|
||||
"",
|
||||
// the callback
|
||||
function (isValid, propertyErrors, allErrors) {
|
||||
if (!isValid) {
|
||||
formCtrl.$setValidity(validationKey, false);
|
||||
}
|
||||
else {
|
||||
formCtrl.$setValidity(validationKey, true);
|
||||
}
|
||||
},
|
||||
currentSegment,
|
||||
matchType ? { matchType: matchType } : null // specify the match type
|
||||
));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if (Utilities.isObject(scope.valServerMatch)) {
|
||||
var allowedKeys = ["contains", "prefix", "suffix"];
|
||||
Object.keys(scope.valServerMatch).forEach(k => {
|
||||
if (allowedKeys.indexOf(k) === -1) {
|
||||
Object.keys(scope.valServerMatch).forEach(matchType => {
|
||||
if (allowedKeys.indexOf(matchType) === -1) {
|
||||
throw "valServerMatch dictionary keys must be one of " + allowedKeys.join();
|
||||
}
|
||||
|
||||
var matchVal = scope.valServerMatch[k];
|
||||
if (Utilities.isString(matchVal)) {
|
||||
matchVal = [matchVal]; // change to an array since the value can also natively be an array
|
||||
}
|
||||
var matchVal = scope.valServerMatch[matchType];
|
||||
|
||||
// match for each string in the array
|
||||
matchVal.forEach(m => {
|
||||
unsubscribe.push(serverValidationManager.subscribe(
|
||||
m,
|
||||
currentCulture,
|
||||
"",
|
||||
serverValidationManagerCallback,
|
||||
currentSegment,
|
||||
{ matchType: k } // specify the match type
|
||||
));
|
||||
})
|
||||
if (Utilities.isObject(matchVal)) {
|
||||
|
||||
// as an object, the key will be the validation error instead of the default "valServerMatch"
|
||||
Object.keys(matchVal).forEach(valKey => {
|
||||
|
||||
// matchVal[valKey] can be an ARRAY or a STRING
|
||||
bindCallback(valKey, matchVal[valKey], matchType);
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
||||
// matchVal can be an ARRAY or a STRING
|
||||
bindCallback("valServerMatch", matchVal, matchType);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (Utilities.isString(scope.valServerMatch)) {
|
||||
unsubscribe.push(serverValidationManager.subscribe(
|
||||
scope.valServerMatch,
|
||||
currentCulture,
|
||||
"",
|
||||
serverValidationManagerCallback,
|
||||
currentSegment));
|
||||
|
||||
// a STRING match which will be an exact match on the string supplied as the property validation key
|
||||
bindCallback("valServerMatch", scope.valServerMatch, null);
|
||||
}
|
||||
else {
|
||||
throw "valServerMatch value must be a string or a dictionary";
|
||||
|
||||
@@ -23,13 +23,17 @@
|
||||
> .umb-block-list__block--actions {
|
||||
opacity: 0;
|
||||
transition: opacity 120ms;
|
||||
|
||||
.--error {
|
||||
color: @formErrorBorder !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:focus-within,
|
||||
&.--active {
|
||||
|
||||
|
||||
> .umb-block-list__block--actions {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<ng-form name="vm.blockRowForm" val-server-match="{ 'contains' : [ vm.layout.$block.content.key, vm.layout.$block.settings.key] }">
|
||||
<ng-form name="vm.blockRowForm" val-server-match="{ 'contains' : { 'valServerMatchContent': vm.layout.$block.content.key, 'valServerMatchSettings': vm.layout.$block.settings.key } }">
|
||||
<div class="umb-block-list__block" ng-class="{'--active':vm.layout.$block.active}">
|
||||
|
||||
<umb-block-list-block stylesheet="{{::vm.layout.$block.config.stylesheet}}"
|
||||
@@ -13,19 +13,23 @@
|
||||
<div class="umb-block-list__block--actions">
|
||||
<button type="button" class="btn-reset umb-outline action --settings" localize="title" title="actions_editSettings"
|
||||
ng-click="vm.blockEditorApi.openSettingsForBlock(vm.layout.$block, vm.index, vm.blockRowForm);"
|
||||
ng-class="{ '--error': vm.blockRowForm.$error.valServerMatchSettings && vm.valFormManager.isShowingValidation() }"
|
||||
ng-if="vm.layout.$block.showSettings === true">
|
||||
<i class="icon icon-settings" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_settings">Settings</localize>
|
||||
</span>
|
||||
</button>
|
||||
<button type="button" class="btn-reset umb-outline action --copy" localize="title" title="actions_copy" ng-click="vm.blockEditorApi.copyBlock(vm.layout.$block);" ng-if="vm.layout.$block.showCopy === true">
|
||||
<button type="button" class="btn-reset umb-outline action --copy" localize="title" title="actions_copy"
|
||||
ng-click="vm.blockEditorApi.copyBlock(vm.layout.$block);"
|
||||
ng-if="vm.layout.$block.showCopy === true">
|
||||
<i class="icon icon-documents" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_copy">Copy</localize>
|
||||
</span>
|
||||
</button>
|
||||
<button type="button" class="btn-reset umb-outline action --delete" localize="title" title="actions_delete" ng-click="vm.blockEditorApi.requestDeleteBlock(vm.layout.$block);">
|
||||
<button type="button" class="btn-reset umb-outline action --delete" localize="title" title="actions_delete"
|
||||
ng-click="vm.blockEditorApi.requestDeleteBlock(vm.layout.$block);">
|
||||
<i class="icon icon-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_delete">Delete</localize>
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
blockEditorApi: "<",
|
||||
layout: "<",
|
||||
index: "<"
|
||||
},
|
||||
require: {
|
||||
valFormManager: "^^valFormManager"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user