Got validation working properly with pre-values, updated the content editing helper to be more generic and work with different editors like the data type editor that supports umb-property.
This commit is contained in:
@@ -38,14 +38,10 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
|
||||
* @description
|
||||
* re-binds all changed property values to the origContent object from the newContent object and returns an array of changed properties.
|
||||
*/
|
||||
reBindChangedProperties: function (origContent, newContent) {
|
||||
reBindChangedProperties: function (allOrigProps, allNewProps) {
|
||||
|
||||
var changed = [];
|
||||
|
||||
//get a list of properties since they are contained in tabs
|
||||
var allOrigProps = this.getAllProps(origContent);
|
||||
var allNewProps = this.getAllProps(newContent);
|
||||
|
||||
function getNewProp(alias) {
|
||||
if (alias.startsWith("_umb_")) {
|
||||
return null;
|
||||
@@ -78,10 +74,8 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
|
||||
* It's worth noting that when a 403 occurs, the data is still saved just never published, though this depends on if the entity is a new
|
||||
* entity and whether or not the data fulfils the absolute basic requirements like having a mandatory Name.
|
||||
*/
|
||||
handleValidationErrors: function (content, modelState) {
|
||||
//get a list of properties since they are contained in tabs
|
||||
var allProps = this.getAllProps(content);
|
||||
|
||||
handleValidationErrors: function (allProps, modelState) {
|
||||
|
||||
//find the content property for the current error, for use in the loop below
|
||||
function findContentProp(props, propAlias) {
|
||||
return _.find(props, function (item) {
|
||||
@@ -132,21 +126,36 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
|
||||
* @description
|
||||
* A function to handle what happens when we have validation issues from the server side
|
||||
*/
|
||||
handleSaveError: function (err, scope) {
|
||||
handleSaveError: function (args) {
|
||||
|
||||
if (!args.err) {
|
||||
throw "args.err cannot be null";
|
||||
}
|
||||
if (!args.allNewProps && !angular.isArray(args.allNewProps)) {
|
||||
throw "args.allNewProps must be a valid array";
|
||||
}
|
||||
if (!args.allOrigProps && !angular.isArray(args.allOrigProps)) {
|
||||
throw "args.allOrigProps must be a valid array";
|
||||
}
|
||||
|
||||
//When the status is a 403 status, we have validation errors.
|
||||
//Otherwise the error is probably due to invalid data (i.e. someone mucking around with the ids or something).
|
||||
//Or, some strange server error
|
||||
if (err.status === 403) {
|
||||
if (args.err.status === 403) {
|
||||
//now we need to look through all the validation errors
|
||||
if (err.data && (err.data.modelState)) {
|
||||
if (args.err.data && (args.err.data.ModelState)) {
|
||||
|
||||
this.handleValidationErrors(args.allNewProps, args.err.data.ModelState);
|
||||
|
||||
this.handleValidationErrors(err.data, err.data.modelState);
|
||||
|
||||
if (!this.redirectToCreatedContent(err.data.id, err.data.modelState)) {
|
||||
if (!this.redirectToCreatedContent(args.err.data.id, args.err.data.ModelState)) {
|
||||
//we are not redirecting because this is not new content, it is existing content. In this case
|
||||
// we need to detect what properties have changed and re-bind them with the server data. Then we need
|
||||
// to re-bind any server validation errors after the digest takes place.
|
||||
this.reBindChangedProperties(scope.content, err.data);
|
||||
|
||||
if (args.rebindCallback && angular.isFunction(args.rebindCallback)) {
|
||||
args.rebindCallback();
|
||||
}
|
||||
|
||||
serverValidationManager.executeAndClearAllSubscriptions();
|
||||
}
|
||||
|
||||
@@ -154,11 +163,11 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
dialogService.ysodDialog(err);
|
||||
dialogService.ysodDialog(args.err);
|
||||
}
|
||||
}
|
||||
else {
|
||||
dialogService.ysodDialog(err);
|
||||
dialogService.ysodDialog(args.err);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -166,7 +175,7 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.contentEditingHelper#handleSaveError
|
||||
* @name umbraco.services.contentEditingHelper#handleSuccessfulSave
|
||||
* @methodOf umbraco.services.contentEditingHelper
|
||||
* @function
|
||||
*
|
||||
|
||||
@@ -85,7 +85,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
* In both of the above, the successCallback must accept these parameters: data, status, headers, config
|
||||
* If using the errorCallback it must accept these parameters: data, status, headers, config
|
||||
* The success callback must return the data which will be resolved by the deferred object.
|
||||
* The error callback must return an object containing: {errorMsg: errorMessage, data: originalData }
|
||||
* The error callback must return an object containing: {errorMsg: errorMessage, data: originalData, status: status }
|
||||
*/
|
||||
resourcePromise: function (httpPromise, opts) {
|
||||
var deferred = $q.defer();
|
||||
@@ -101,7 +101,8 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
return {
|
||||
//NOTE: the default error message here should never be used based on the above docs!
|
||||
errorMsg: (angular.isString(opts) ? opts : 'An error occurred!'),
|
||||
data: data
|
||||
data: data,
|
||||
status: status
|
||||
};
|
||||
}
|
||||
|
||||
@@ -137,7 +138,8 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ
|
||||
//return an error object including the error message for UI
|
||||
deferred.reject({
|
||||
errorMsg: result.errorMsg,
|
||||
data: result.data
|
||||
data: result.data,
|
||||
status: result.status
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -61,11 +61,22 @@ function ContentEditController($scope, $routeParams, $location, contentResource,
|
||||
contentEditingHelper.handleSuccessfulSave({
|
||||
scope: $scope,
|
||||
newContent: data,
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties(scope.content, data)
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties(
|
||||
contentEditingHelper.getAllProps($scope.content),
|
||||
contentEditingHelper.getAllProps(data))
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
contentEditingHelper.handleSaveError(err, $scope);
|
||||
}, function (err) {
|
||||
|
||||
var allNewProps = contentEditingHelper.getAllProps(err.data);
|
||||
var allOrigProps = contentEditingHelper.getAllProps($scope.content);
|
||||
|
||||
contentEditingHelper.handleSaveError({
|
||||
err: err,
|
||||
allNewProps: allNewProps,
|
||||
allOrigProps: contentEditingHelper.getAllProps($scope.content),
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties(allOrigProps, allNewProps)
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -89,7 +100,11 @@ function ContentEditController($scope, $routeParams, $location, contentResource,
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
contentEditingHelper.handleSaveError(err, $scope);
|
||||
contentEditingHelper.handleSaveError({
|
||||
err: err,
|
||||
allNewProps: contentEditingHelper.getAllProps(err.data),
|
||||
allOrigProps: contentEditingHelper.getAllProps($scope.content)
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -102,7 +102,17 @@ function DataTypeEditController($scope, $routeParams, $location, dataTypeResourc
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
contentEditingHelper.handleSaveError(err, $scope);
|
||||
|
||||
//NOTE: in the case of data type values we are setting the orig/new props
|
||||
// to be the same thing since that only really matters for content/media.
|
||||
contentEditingHelper.handleSaveError({
|
||||
err: err,
|
||||
allNewProps: $scope.preValues,
|
||||
allOrigProps: $scope.preValues,
|
||||
rebindCallback: function () {
|
||||
createPreValueProps(err.data.preValues);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -59,11 +59,22 @@ function mediaEditController($scope, $routeParams, mediaResource, notificationsS
|
||||
contentEditingHelper.handleSuccessfulSave({
|
||||
scope: $scope,
|
||||
newContent: data,
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties(scope.content, data)
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties(
|
||||
contentEditingHelper.getAllProps($scope.content),
|
||||
contentEditingHelper.getAllProps(data))
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
contentEditingHelper.handleSaveError(err, $scope);
|
||||
|
||||
var allNewProps = contentEditingHelper.getAllProps(err.data);
|
||||
var allOrigProps = contentEditingHelper.getAllProps($scope.content);
|
||||
|
||||
contentEditingHelper.handleSaveError({
|
||||
err: err,
|
||||
allNewProps: allNewProps,
|
||||
allOrigProps: contentEditingHelper.getAllProps($scope.content),
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties(allOrigProps, allNewProps)
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<div>
|
||||
<input name="requiredField" type="text" id="{{model.alias}}" class="umb-textstring span7 textstring"
|
||||
ng-model="model.value"
|
||||
required />
|
||||
val-server="value"/>
|
||||
|
||||
<span class="help-inline" val-msg-for="requiredField" val-toggle-msg="required">Required</span>
|
||||
|
||||
<span class="help-inline" val-msg-for="requiredField" val-toggle-msg="valServer">{{propertyForm.requiredField.errorMsg}}</span>
|
||||
</div>
|
||||
|
||||
@@ -22,10 +22,14 @@ describe('contentEditingHelper tests', function () {
|
||||
data: content,
|
||||
status: 403
|
||||
};
|
||||
err.data.modelState = {};
|
||||
err.data.ModelState = {};
|
||||
|
||||
//act
|
||||
var handled = contentEditingHelper.handleSaveError(err, {content: content});
|
||||
var handled = contentEditingHelper.handleSaveError({
|
||||
err: err,
|
||||
allNewProps: contentEditingHelper.getAllProps(content),
|
||||
allOrigProps: contentEditingHelper.getAllProps(content)
|
||||
});
|
||||
|
||||
//assert
|
||||
expect(handled).toBe(true);
|
||||
@@ -39,7 +43,11 @@ describe('contentEditingHelper tests', function () {
|
||||
};
|
||||
|
||||
//act
|
||||
var handled = contentEditingHelper.handleSaveError(err, null);
|
||||
var handled = contentEditingHelper.handleSaveError({
|
||||
err: err,
|
||||
allNewProps: [],
|
||||
allOrigProps: []
|
||||
});
|
||||
|
||||
//assert
|
||||
expect(handled).toBe(false);
|
||||
@@ -55,7 +63,11 @@ describe('contentEditingHelper tests', function () {
|
||||
};
|
||||
|
||||
//act
|
||||
var handled = contentEditingHelper.handleSaveError(err, { content: content });
|
||||
var handled = contentEditingHelper.handleSaveError({
|
||||
err: err,
|
||||
allNewProps: contentEditingHelper.getAllProps(content),
|
||||
allOrigProps: contentEditingHelper.getAllProps(content)
|
||||
});
|
||||
|
||||
//assert
|
||||
expect(handled).toBe(false);
|
||||
@@ -69,9 +81,10 @@ describe('contentEditingHelper tests', function () {
|
||||
|
||||
//arrange
|
||||
var content = mocksUtils.getMockContent(1234);
|
||||
var allProps = contentEditingHelper.getAllProps(content);
|
||||
|
||||
//act
|
||||
contentEditingHelper.handleValidationErrors(content, { Name: ["Required"] });
|
||||
contentEditingHelper.handleValidationErrors(allProps, { Name: ["Required"] });
|
||||
|
||||
//assert
|
||||
expect(serverValidationManager.items.length).toBe(1);
|
||||
@@ -84,9 +97,10 @@ describe('contentEditingHelper tests', function () {
|
||||
|
||||
//arrange
|
||||
var content = mocksUtils.getMockContent(1234);
|
||||
var allProps = contentEditingHelper.getAllProps(content);
|
||||
|
||||
//act
|
||||
contentEditingHelper.handleValidationErrors(content, { "Property.bodyText": ["Required"] });
|
||||
contentEditingHelper.handleValidationErrors(allProps, { "Property.bodyText": ["Required"] });
|
||||
|
||||
//assert
|
||||
expect(serverValidationManager.items.length).toBe(1);
|
||||
@@ -99,9 +113,10 @@ describe('contentEditingHelper tests', function () {
|
||||
|
||||
//arrange
|
||||
var content = mocksUtils.getMockContent(1234);
|
||||
var allProps = contentEditingHelper.getAllProps(content);
|
||||
|
||||
//act
|
||||
contentEditingHelper.handleValidationErrors(content, { "Property.bodyText.value": ["Required"] });
|
||||
contentEditingHelper.handleValidationErrors(allProps, { "Property.bodyText.value": ["Required"] });
|
||||
|
||||
//assert
|
||||
expect(serverValidationManager.items.length).toBe(1);
|
||||
@@ -114,10 +129,11 @@ describe('contentEditingHelper tests', function () {
|
||||
|
||||
//arrange
|
||||
var content = mocksUtils.getMockContent(1234);
|
||||
var allProps = contentEditingHelper.getAllProps(content);
|
||||
|
||||
//act
|
||||
contentEditingHelper.handleValidationErrors(
|
||||
content,
|
||||
allProps,
|
||||
{
|
||||
"Name": ["Required"],
|
||||
"UpdateDate": ["Invalid date"],
|
||||
@@ -202,7 +218,9 @@ describe('contentEditingHelper tests', function () {
|
||||
newContent.tabs[1].properties[2].value = "origValue4";
|
||||
|
||||
//act
|
||||
var changed = contentEditingHelper.reBindChangedProperties(origContent, newContent);
|
||||
var changed = contentEditingHelper.reBindChangedProperties(
|
||||
contentEditingHelper.getAllProps(origContent),
|
||||
contentEditingHelper.getAllProps(newContent));
|
||||
|
||||
//assert
|
||||
expect(changed.length).toBe(2);
|
||||
|
||||
Reference in New Issue
Block a user