diff --git a/src/Umbraco.Core/PropertyEditors/DelimitedValueValidator.cs b/src/Umbraco.Core/PropertyEditors/DelimitedValueValidator.cs
index 411c7c3abe..459038829d 100644
--- a/src/Umbraco.Core/PropertyEditors/DelimitedValueValidator.cs
+++ b/src/Umbraco.Core/PropertyEditors/DelimitedValueValidator.cs
@@ -11,7 +11,7 @@ namespace Umbraco.Core.PropertyEditors
/// A validator that validates a delimited set of values against a common regex
///
[ValueValidator("Delimited")]
- internal sealed class DelimitedValueValidator : ManifestValueValidator
+ internal sealed class DelimitedValueValidator : ValueValidator
{
///
/// Performs the validation
diff --git a/src/Umbraco.Core/PropertyEditors/ManifestValidator.cs b/src/Umbraco.Core/PropertyEditors/ManifestValidator.cs
index 6fcc86318c..0252bd9abf 100644
--- a/src/Umbraco.Core/PropertyEditors/ManifestValidator.cs
+++ b/src/Umbraco.Core/PropertyEditors/ManifestValidator.cs
@@ -27,12 +27,12 @@ namespace Umbraco.Core.PropertyEditors
[JsonConverter(typeof(JsonToStringConverter))]
public string Config { get; set; }
- private ManifestValueValidator _validatorInstance;
+ private ValueValidator _validatorInstance;
///
/// Gets the ValueValidator instance
///
- internal ManifestValueValidator ValidatorInstance
+ internal ValueValidator ValidatorInstance
{
get
{
@@ -41,7 +41,7 @@ namespace Umbraco.Core.PropertyEditors
var val = ValidatorsResolver.Current.GetValidator(Type);
if (val == null)
{
- throw new InvalidOperationException("No " + typeof(ManifestValueValidator) + " could be found for the type name of " + Type);
+ throw new InvalidOperationException("No " + typeof(ValueValidator) + " could be found for the type name of " + Type);
}
_validatorInstance = val;
}
diff --git a/src/Umbraco.Core/PropertyEditors/RegexValueValidator.cs b/src/Umbraco.Core/PropertyEditors/RegexValueValidator.cs
index 840a76670b..705db74e84 100644
--- a/src/Umbraco.Core/PropertyEditors/RegexValueValidator.cs
+++ b/src/Umbraco.Core/PropertyEditors/RegexValueValidator.cs
@@ -9,7 +9,7 @@ namespace Umbraco.Core.PropertyEditors
/// A validator that validates that the value against a Regex expression
///
[ValueValidator("Regex")]
- internal sealed class RegexValueValidator : ManifestValueValidator
+ internal sealed class RegexValueValidator : ValueValidator
{
public override IEnumerable Validate(string value, string config, string preValues, PropertyEditor editor)
{
diff --git a/src/Umbraco.Core/PropertyEditors/RequiredValueValidator.cs b/src/Umbraco.Core/PropertyEditors/RequiredValueValidator.cs
index 41fa14d927..7990998d9e 100644
--- a/src/Umbraco.Core/PropertyEditors/RequiredValueValidator.cs
+++ b/src/Umbraco.Core/PropertyEditors/RequiredValueValidator.cs
@@ -7,7 +7,7 @@ namespace Umbraco.Core.PropertyEditors
/// A validator that validates that the value is not null or empty (if it is a string)
///
[ValueValidator("Required")]
- internal sealed class RequiredValueValidator : ManifestValueValidator
+ internal sealed class RequiredValueValidator : ValueValidator
{
public override IEnumerable Validate(string value, string config, string preValues, PropertyEditor editor)
{
diff --git a/src/Umbraco.Core/PropertyEditors/ValidatorsResolver.cs b/src/Umbraco.Core/PropertyEditors/ValidatorsResolver.cs
index 4b1f0b7c28..a23c6a3c2c 100644
--- a/src/Umbraco.Core/PropertyEditors/ValidatorsResolver.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValidatorsResolver.cs
@@ -8,7 +8,7 @@ namespace Umbraco.Core.PropertyEditors
///
/// A resolver to resolve all registered validators
///
- internal class ValidatorsResolver : LazyManyObjectsResolverBase
+ internal class ValidatorsResolver : LazyManyObjectsResolverBase
{
public ValidatorsResolver(IEnumerable> lazyTypeList)
: base(lazyTypeList, ObjectLifetimeScope.Application)
@@ -18,7 +18,7 @@ namespace Umbraco.Core.PropertyEditors
///
/// Returns the validators
///
- public IEnumerable Validators
+ public IEnumerable Validators
{
get { return Values; }
}
@@ -28,7 +28,7 @@ namespace Umbraco.Core.PropertyEditors
///
///
///
- public ManifestValueValidator GetValidator(string name)
+ public ValueValidator GetValidator(string name)
{
return Values.FirstOrDefault(x => x.TypeName == name);
}
diff --git a/src/Umbraco.Core/PropertyEditors/ValueEditor.cs b/src/Umbraco.Core/PropertyEditors/ValueEditor.cs
index 8bd0434deb..258444ba69 100644
--- a/src/Umbraco.Core/PropertyEditors/ValueEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueEditor.cs
@@ -50,6 +50,34 @@ namespace Umbraco.Core.PropertyEditors
[JsonProperty("validation")]
public IEnumerable Validators { get; set; }
+ ///
+ /// Returns the validator used for the required field validation which is specified on the PropertyType
+ ///
+ ///
+ /// This will become legacy as soon as we implement overridable pre-values.
+ ///
+ /// The default validator used is the RequiredValueValidator but this can be overridden by property editors
+ /// if they need to do some custom validation, or if the value being validated is a json object.
+ ///
+ internal virtual ValueValidator RequiredValidator
+ {
+ get { return new RequiredValueValidator(); }
+ }
+
+ ///
+ /// Returns the validator used for the regular expression field validation which is specified on the PropertyType
+ ///
+ ///
+ /// This will become legacy as soon as we implement overridable pre-values.
+ ///
+ /// The default validator used is the RegexValueValidator but this can be overridden by property editors
+ /// if they need to do some custom validation, or if the value being validated is a json object.
+ ///
+ internal virtual ValueValidator RegexValidator
+ {
+ get { return new RegexValueValidator(); }
+ }
+
///
/// Returns the true DataTypeDatabaseType from the string representation ValueType
///
diff --git a/src/Umbraco.Core/PropertyEditors/ValueTypeValueValidator.cs b/src/Umbraco.Core/PropertyEditors/ValueTypeValueValidator.cs
index 5295b6b92a..5b50ba3ccf 100644
--- a/src/Umbraco.Core/PropertyEditors/ValueTypeValueValidator.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueTypeValueValidator.cs
@@ -12,7 +12,7 @@ namespace Umbraco.Core.PropertyEditors
/// This is a special validator type that is executed against all property editors no matter if they've defined this validator or not.
///
[ValueValidator("ValueType")]
- internal sealed class ValueTypeValueValidator : ManifestValueValidator
+ internal sealed class ValueTypeValueValidator : ValueValidator
{
public override IEnumerable Validate(string value, string config, string preValues, PropertyEditor editor)
{
diff --git a/src/Umbraco.Core/PropertyEditors/ManifestValueValidator.cs b/src/Umbraco.Core/PropertyEditors/ValueValidator.cs
similarity index 93%
rename from src/Umbraco.Core/PropertyEditors/ManifestValueValidator.cs
rename to src/Umbraco.Core/PropertyEditors/ValueValidator.cs
index e734992501..adc8f90da5 100644
--- a/src/Umbraco.Core/PropertyEditors/ManifestValueValidator.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueValidator.cs
@@ -1,42 +1,42 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-
-namespace Umbraco.Core.PropertyEditors
-{
- ///
- /// A validator used to validate a value based on a validator name defined in a package manifest
- ///
- internal abstract class ManifestValueValidator
- {
- protected ManifestValueValidator()
- {
- var att = this.GetType().GetCustomAttribute(false);
- if (att == null)
- {
- throw new InvalidOperationException("The class " + GetType() + " is not attributed with the " + typeof(ValueValidatorAttribute) + " attribute");
- }
- TypeName = att.TypeName;
- }
-
- public string TypeName { get; private set; }
-
- ///
- /// Performs the validation against the value
- ///
- ///
- ///
- /// An object that is used to configure the validator. An example could be a regex
- /// expression if the validator was a regex validator. This is defined in the manifest along with
- /// the definition of the validator.
- ///
- /// The current pre-values stored for the data type
- /// The property editor instance that is being validated
- ///
- /// Returns a list of validation results. If a result does not have a field name applied to it then then we assume that
- /// the validation message applies to the entire property type being validated. If there is a field name applied to a
- /// validation result we will try to match that field name up with a field name on the item itself.
- ///
- public abstract IEnumerable Validate(string value, string config, string preValues, PropertyEditor editor);
- }
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+
+namespace Umbraco.Core.PropertyEditors
+{
+ ///
+ /// A validator used to validate a value based on a validator name defined in a package manifest
+ ///
+ internal abstract class ValueValidator
+ {
+ protected ValueValidator()
+ {
+ var att = this.GetType().GetCustomAttribute(false);
+ if (att == null)
+ {
+ throw new InvalidOperationException("The class " + GetType() + " is not attributed with the " + typeof(ValueValidatorAttribute) + " attribute");
+ }
+ TypeName = att.TypeName;
+ }
+
+ public string TypeName { get; private set; }
+
+ ///
+ /// Performs the validation against the value
+ ///
+ ///
+ ///
+ /// An object that is used to configure the validator. An example could be a regex
+ /// expression if the validator was a regex validator. This is defined in the manifest along with
+ /// the definition of the validator.
+ ///
+ /// The current pre-values stored for the data type
+ /// The property editor instance that is being validated
+ ///
+ /// Returns a list of validation results. If a result does not have a field name applied to it then then we assume that
+ /// the validation message applies to the entire property type being validated. If there is a field name applied to a
+ /// validation result we will try to match that field name up with a field name on the item itself.
+ ///
+ public abstract IEnumerable Validate(string value, string config, string preValues, PropertyEditor editor);
+ }
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 1b714f48ad..3581d15a00 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -547,7 +547,7 @@
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/valbubble.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/valbubble.directive.js
deleted file mode 100644
index 8068009be2..0000000000
--- a/src/Umbraco.Web.UI.Client/src/common/directives/valbubble.directive.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
-* @ngdoc directive
-* @name umbraco.directive:valBubble
-* @restrict A
-* @description This directive will bubble up a notification via an emit event (upwards)
- describing the state of the validation element. This is useful for
- parent elements to know about child element validation state.
-**/
-function valBubble() {
- return {
- require: ['ngModel', '^form'],
- link: function (scope, element, attr, ctrls) {
-
- if (!attr.name) {
- throw "valBubble must be set on an input element that has a 'name' attribute";
- }
-
- var modelCtrl = ctrls[0];
- var formCtrl = ctrls[1];
-
- //watch the current form's validation for the current field name
- scope.$watch(formCtrl.$name + "." + modelCtrl.$name + ".$valid", function (isValid, lastValue) {
- if (isValid !== undefined) {
- //emit an event upwards
- scope.$emit("valBubble", {
- isValid: isValid, // if the field is valid
- element: element, // the element that the validation applies to
- expression: this.exp, // the expression that was watched to check validity
- scope: scope, // the current scope
- formCtrl: formCtrl // the current form controller
- });
- }
- });
- }
- };
-}
-angular.module('umbraco.directives').directive("valBubble", valBubble);
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/valpropertymsg.directive.js
index c5dca948b2..3e55b7e762 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/valpropertymsg.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/valpropertymsg.directive.js
@@ -4,15 +4,17 @@
* @restrict A
* @description This directive is used to control the display of the property level validation message.
* We will listen for server side validation changes
- * and when an error is detected for this property we'll show the error message and then we need
- * to emit the valBubble event so that any parent listening can update it's UI (like the validation summary)
+ * and when an error is detected for this property we'll show the error message
**/
function valPropertyMsg(serverValidationService) {
- return {
+ return {
+ scope: {
+ currentProperty: "=property"
+ },
require: "^form", //require that this directive is contained within an ngForm
replace: true, //replace the element with the template
restrict: "E", //restrict to element
- template: "
{{errorMsg}}
",
+ template: "
{{errorMsg}}
",
/**
* @ngdoc function
@@ -26,11 +28,9 @@ function valPropertyMsg(serverValidationService) {
* @param formCtrl {FormController} Our directive requries a reference to a form controller which gets passed in to this parameter
*/
link: function (scope, element, attrs, formCtrl) {
-
- if (!attrs.property) {
- throw "the valPropertyMsg requires an attribute 'property' set which equals the current content property object";
- }
- var currentProperty = scope.$eval(attrs.property);
+
+ //assign the form control to our isolated scope so we can watch it's values
+ scope.formCtrl = formCtrl;
//flags for use in the below closures
var showValidation = false;
@@ -39,19 +39,26 @@ function valPropertyMsg(serverValidationService) {
//create properties on our custom scope so we can use it in our template
scope.errorMsg = "";
- //listen for form validation
- scope.$watch(formCtrl.$name + ".$valid", function (isValid, oldValue) {
- if (isValid === undefined) {
+ //listen for error changes
+ scope.$watch("formCtrl.$error", function () {
+ if (formCtrl.$valid === undefined) {
return;
}
- if (!isValid) {
- //check if it's one of the properties that is invalid in the current content property
- if (element.closest(".umb-control-group").find(".ng-invalid").length > 0) {
+ if (!formCtrl.$valid) {
+
+ //first we need to check if the valPropertyMsg validity is invalid
+ if (formCtrl.$error.valPropertyMsg && formCtrl.$error.valPropertyMsg.length > 0) {
+ //since we already have an error we'll just return since this means we've already set the
+ // hasError and errorMsg properties which occurs below in the serverValidationService.subscribe
+ return;
+ }
+ else if (element.closest(".umb-control-group").find(".ng-invalid").length > 0) {
+ //check if it's one of the properties that is invalid in the current content property
hasError = true;
- if (showValidation && scope.errorMsg === "") {
- //update the validation message
- scope.errorMsg = serverValidationService.getError(currentProperty, "");
+ //update the validation message if we don't already have one assigned.
+ if (showValidation && scope.errorMsg === "") {
+ scope.errorMsg = serverValidationService.getError(scope.currentProperty, "");
}
}
else {
@@ -63,13 +70,13 @@ function valPropertyMsg(serverValidationService) {
hasError = false;
scope.errorMsg = "";
}
- });
+ }, true);
//listen for the forms saving event
scope.$on("saving", function (ev, args) {
showValidation = true;
if (hasError && scope.errorMsg === "") {
- scope.errorMsg = serverValidationService.getError(currentProperty, "");
+ scope.errorMsg = serverValidationService.getError(scope.currentProperty, "");
}
else if (!hasError) {
scope.errorMsg = "";
@@ -80,45 +87,51 @@ function valPropertyMsg(serverValidationService) {
scope.$on("saved", function (ev, args) {
showValidation = false;
scope.errorMsg = "";
+ formCtrl.$setValidity('valPropertyMsg', true);
});
+ //We need to subscribe to any changes to our model (based on user input)
+ // This is required because when we have a server error we actually invalidate
+ // the form which means it cannot be resubmitted.
+ // So once a field is changed that has a server error assigned to it
+ // we need to re-validate it for the server side validator so the user can resubmit
+ // the form. Of course normal client-side validators will continue to execute.
+ scope.$watch("currentProperty.value", function(newValue) {
+ if (formCtrl.$invalid) {
+ scope.errorMsg = "";
+ formCtrl.$setValidity('valPropertyMsg', true);
+ }
+ });
+
//listen for server validation changes
// NOTE: we pass in "" in order to listen for all validation changes to the content property, not for
// validation changes to fields in the property this is because some server side validators may not
// return the field name for which the error belongs too, just the property for which it belongs.
- serverValidationService.subscribe(currentProperty, "", function (isValid, propertyErrors, allErrors) {
+ serverValidationService.subscribe(scope.currentProperty, "", function (isValid, propertyErrors, allErrors) {
hasError = !isValid;
if (hasError) {
//set the error message to the server message
- scope.errorMsg = propertyErrors[0].errorMsg;
+ scope.errorMsg = propertyErrors[0].errorMsg;
//now that we've used the server validation message, we need to remove it from the
//error collection... it is a 'one-time' usage so that when the field is invalidated
//again, the message we display is the client side message.
//NOTE: 'this' in the subscribe callback context is the validation manager object.
- this.removeError(scope.model);
- //emit an event upwards
- scope.$emit("valBubble", {
- isValid: false, // it is INVALID
- element: element, // the element that the validation applies to
- scope: scope, // the scope
- formCtrl: formCtrl // the current form controller
- });
+ this.removeError(scope.currentProperty);
+ //flag that the current validator is invalid
+ formCtrl.$setValidity('valPropertyMsg', false);
}
else {
scope.errorMsg = "";
- //emit an event upwards
- scope.$emit("valBubble", {
- isValid: true, // it is VALID
- element: element, // the element that the validation applies to
- scope: scope, // the scope
- formCtrl: formCtrl // the current form controller
- });
+ //flag that the current validator is valid
+ formCtrl.$setValidity('valPropertyMsg', true);
}
});
//when the element is disposed we need to unsubscribe!
+ // NOTE: this is very important otherwise when this controller re-binds the previous subscriptsion will remain
+ // but they are a different callback instance than the above.
element.bind('$destroy', function () {
- serverValidationService.unsubscribe(currentProperty, "");
+ serverValidationService.unsubscribe(scope.currentProperty, "");
});
}
};
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/valserver.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/valserver.directive.js
index edfb151397..0d8c36f41c 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/valserver.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/valserver.directive.js
@@ -22,23 +22,19 @@ function valServer(serverValidationService) {
fieldName = attr.valServer;
}
- //subscribe to the changed event of the element. This is required because when we
+ //subscribe to the changed event of the view model. This is required because when we
// have a server error we actually invalidate the form which means it cannot be
// resubmitted. So once a field is changed that has a server error assigned to it
// we need to re-validate it for the server side validator so the user can resubmit
// the form. Of course normal client-side validators will continue to execute.
- element.keydown(function () {
+ ctrl.$viewChangeListeners.push(function () {
if (ctrl.$invalid) {
ctrl.$setValidity('valServer', true);
+ //emit the event upwards
+ scope.$emit("serverRevalidated", { modelCtrl: ctrl });
}
});
- element.change(function () {
- if (ctrl.$invalid) {
- ctrl.$setValidity('valServer', true);
- }
- });
- //TODO: DO we need to watch for other changes on the element ?
-
+
//subscribe to the server validation changes
serverValidationService.subscribe(currentProperty, fieldName, function (isValid, propertyErrors, allErrors) {
if (!isValid) {
@@ -54,6 +50,8 @@ function valServer(serverValidationService) {
});
//when the element is disposed we need to unsubscribe!
+ // NOTE: this is very important otherwise when this controller re-binds the previous subscriptsion will remain
+ // but they are a different callback instance than the above.
element.bind('$destroy', function () {
serverValidationService.unsubscribe(currentProperty, fieldName);
});
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/valsummary.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/valsummary.directive.js
deleted file mode 100644
index 30628cd37f..0000000000
--- a/src/Umbraco.Web.UI.Client/src/common/directives/valsummary.directive.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * @ngdoc directive
- * @name umbraco.directive:valSummary
- * @restrict E
- * @description This directive will display a validation summary for the current form based on the
- content properties of the current content item.
- **/
-function valSummary() {
- return {
- scope: true, // create a new scope for this directive
- replace: true, // replace the html element with the template
- restrict: "E", // restrict to an element
- template: '
{{model}}
',
- link: function (scope, element, attr, ctrl) {
-
- //create properties on our custom scope so we can use it in our template
- scope.validationSummary = [];
-
- //create a flag for us to be able to reference in the below closures for watching.
- var showValidation = false;
-
- //add a watch to update our waitingOnValidation flag for use in the below closures
- scope.$watch("$parent.ui.waitingOnValidation", function (isWaiting, oldValue) {
- showValidation = isWaiting;
- if (scope.validationSummary.length > 0 && showValidation) {
- element.show();
- }
- else {
- element.hide();
- }
- });
-
- //if we are to show field property based errors.
- //this requires listening for bubbled events from valBubble directive.
-
- scope.$parent.$on("valBubble", function (evt, args) {
- var msg = "The value assigned for the property " + args.scope.model.label + " is invalid";
- var exists = _.contains(scope.validationSummary, msg);
-
- //we need to check if the entire property is valid, even though the args says this field is valid there
- // may be multiple values attached to a content property. The easiest way to do this is check the DOM
- // just like we are doing for the property level validation message.
- var propertyHasErrors = args.element.closest(".content-property").find(".ng-invalid").length > 0;
-
- if (args.isValid && exists && !propertyHasErrors) {
- //it is valid but we have a val msg for it so we'll need to remove the message
- scope.validationSummary = _.reject(scope.validationSummary, function (item) {
- return item === msg;
- });
- }
- else if (!args.isValid && !exists) {
- //it is invalid and we don't have a msg for it already
- scope.validationSummary.push(msg);
- }
-
- //show the summary if there are errors and the form has been submitted
- if (showValidation && scope.validationSummary.length > 0) {
- element.show();
- }
- });
- //listen for form invalidation so we know when to hide it
- scope.$watch("contentForm.$error", function (errors) {
- //check if there is an error and hide the summary if not
- var hasError = _.find(errors, function (err) {
- return (err.length && err.length > 0);
- });
- if (!hasError) {
- element.hide();
- }
- }, true);
- }
- };
-}
-angular.module('umbraco.directives').directive("valSummary", valSummary);
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/valtogglemsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/valtogglemsg.directive.js
index a449bc1bb8..7b00bb670e 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/valtogglemsg.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/valtogglemsg.directive.js
@@ -12,7 +12,7 @@ function valToggleMsg() {
/**
* @ngdoc function
* @name link
- * @methodOf valPropertyMsg
+ * @methodOf valServer
* @function
*
* @description
diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/CsvEditor.html b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/CsvEditor.html
index 8ff6a74615..a301800a4d 100644
--- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/CsvEditor.html
+++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/CsvEditor.html
@@ -3,7 +3,6 @@
{{multiFormVal.myPackage_multiVal.errorMsg}}
diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/PostcodeEditor.html b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/PostcodeEditor.html
index 9a5a5f05b8..93aecdfa1e 100644
--- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/PostcodeEditor.html
+++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/PostcodeEditor.html
@@ -4,8 +4,7 @@
+ val-postcode="model.config.country"/>
{{propertyForm.myPackage_postcode.errorMsg}}{{propertyForm.myPackage_postcode.errorMsg}}
diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/RegexEditor.html b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/RegexEditor.html
index 6397d5dab4..8e4304fbc2 100644
--- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/RegexEditor.html
+++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/PropertyEditors/Views/RegexEditor.html
@@ -7,8 +7,7 @@
type="text" ng-model="model.value"
required
val-regex="model.config"
- val-server="value"
- val-bubble />
+ val-server="value" />
Required!{{propertyForm.regex.errorMsg}}
diff --git a/src/Umbraco.Web.UI/umbraco/js/guiFunctions.js b/src/Umbraco.Web.UI/umbraco/js/guiFunctions.js
index 60a5acf497..2a802dce31 100644
--- a/src/Umbraco.Web.UI/umbraco/js/guiFunctions.js
+++ b/src/Umbraco.Web.UI/umbraco/js/guiFunctions.js
@@ -23,7 +23,6 @@ function toggleTree(sender) {
}
function resizePage(sender) {
-// alert(jQuery(window) + ", " + sender);
var dashboard = jQuery("#rightDIV");
var dashboardFrame = jQuery("#right");
var tree = jQuery("#leftDIV");
@@ -63,51 +62,11 @@ function resizePage(sender) {
treeToggle.show();
uiArea.show();
}
-
- /*
- var dashboard = document.getElementById("rightDIV");
- var dashboardFrame = document.getElementById("right");
- var tree = document.getElementById("leftDIV");
- var appIcons = document.getElementById("PlaceHolderAppIcons");
- var uiArea = document.getElementById("uiArea");
-
- var clientHeight = getViewportHeight() - 48;
- var clientWidth = getViewportWidth();
-
- var leftWidth = parseInt(clientWidth * 0.25);
- var rightWidth = clientWidth - leftWidth - 35; // parseInt(clientWidth*0.65);
-
-
- // check if appdock is present
- var treeHeight = parseInt(clientHeight-5);
-
- if (appIcons != null) {
- treeHeight = treeHeight - 135;
- resizeGuiWindow("PlaceHolderAppIcons", leftWidth, 140);
- }
-
- resizeGuiWindow("treeWindow", leftWidth, treeHeight)
-
- if (tree.style.display == "none") {
- var frameWidth = getViewportWidth() - 24;
- dashboard.style.width = frameWidth + "px";
- } else if (rightWidth > 0) {
- dashboard.style.width = rightWidth + "px";
- }
- if (clientHeight > 0) {
- dashboard.style.height = (clientHeight) + "px";
- //dashboardFrame.style.height = (clientHeight) + "px";
-
- document.getElementById('treeToggle').style.height = (clientHeight) + "px";
- }
- document.getElementById('treeToggle').style.visibility = "visible";
-
- uiArea.style.visibility = "visible";
- */
+
}
function resizeGuiWindow(windowName, newWidth, newHeight, window) {
- resizePanelTo(windowName, false, newWidth, newHeight);
+ //This no longer does anything and shouldn't be used.
}
function resizeGuiWindowWithTabs(windowName, newWidth, newHeight) {
diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs
index e16cbb3d2f..42782b1b14 100644
--- a/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/ContentPropertyDto.cs
@@ -11,8 +11,9 @@ namespace Umbraco.Web.Models.ContentEditing
{
public IDataTypeDefinition DataType { get; set; }
public string Label { get; set; }
- public string Alias { get; set; }
public string Description { get; set; }
public PropertyEditor PropertyEditor { get; set; }
+ public bool IsRequired { get; set; }
+ public string ValidationRegExp { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/Mapping/BaseContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/BaseContentModelMapper.cs
index add6c5a15b..f870871e87 100644
--- a/src/Umbraco.Web/Models/Mapping/BaseContentModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/BaseContentModelMapper.cs
@@ -25,6 +25,8 @@ namespace Umbraco.Web.Models.Mapping
{
return CreateContent, ContentPropertyDto, TPersisted>(content, null, (propertyDto, originalProperty, propEditor) =>
{
+ propertyDto.IsRequired = originalProperty.PropertyType.Mandatory;
+ propertyDto.ValidationRegExp = originalProperty.PropertyType.ValidationRegExp;
propertyDto.Alias = originalProperty.Alias;
propertyDto.Description = originalProperty.PropertyType.Description;
propertyDto.Label = originalProperty.PropertyType.Name;
diff --git a/src/Umbraco.Web/WebApi/Filters/ContentItemValidationFilterAttribute.cs b/src/Umbraco.Web/WebApi/Filters/ContentItemValidationFilterAttribute.cs
index 9f05e58cc0..58a8c7a275 100644
--- a/src/Umbraco.Web/WebApi/Filters/ContentItemValidationFilterAttribute.cs
+++ b/src/Umbraco.Web/WebApi/Filters/ContentItemValidationFilterAttribute.cs
@@ -5,6 +5,7 @@ using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
+using System.Web.UI;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
@@ -88,7 +89,6 @@ namespace Umbraco.Web.WebApi.Filters
return true;
}
- //TODO: Validate the property type data
private bool ValidateData(ContentItemBasic postedItem, HttpActionContext actionContext)
{
foreach (var p in postedItem.ContentDto.Properties)
@@ -135,6 +135,26 @@ namespace Umbraco.Web.WebApi.Filters
}
}
}
+
+ //Now we need to validate the property based on the PropertyType validation (i.e. regex and required)
+ // NOTE: These will become legacy once we have pre-value overrides.
+ if (p.IsRequired)
+ {
+ foreach (var result in p.PropertyEditor.ValueEditor.RequiredValidator.Validate(postedValue, "", preValues, editor))
+ {
+ //add a model state error for the entire property
+ actionContext.ModelState.AddModelError(p.Alias, result.ErrorMessage);
+ }
+ }
+
+ if (!p.ValidationRegExp.IsNullOrWhiteSpace())
+ {
+ foreach (var result in p.PropertyEditor.ValueEditor.RegexValidator.Validate(postedValue, p.ValidationRegExp, preValues, editor))
+ {
+ //add a model state error for the entire property
+ actionContext.ModelState.AddModelError(p.Alias, result.ErrorMessage);
+ }
+ }
}
//create the response if there any errors