问题
I am learning knockout, Durandal and Breeze and thanks to the JumpStart SPA video from John Papa this is a pleasure. So I examine the code of this project and right now I am trying to change the validation mechanism.
At this time, when saving changes, if the save failed, we collect the errors and display a toast with a resume of the errors.
What I would like to achieve is:
having the ability to mark fields not valid in red (background-color) in the view
when a toast is displayed with the validation errors resume (something like: 'Save failed: affairNr is required' ) I would like to replace the property name with a more friendly name (something like 'Save failed: affair number is required')
Here is the portion code for the validation in the datacontext.js:
var saveChanges = function () {
return manager.saveChanges()
.then(saveSucceeded)
.fail(saveFailed);
function saveSucceeded(saveResult) {
log('Saved data successfully', saveResult, true);
}
function saveFailed(error) {
var msg = 'Save failed: ' + getErrorMessages(error);
logError(msg, error);
error.message = msg;
throw error;
}
};
function getErrorMessages(error) {
var msg = error.message;
if (msg.match(/validation error/i)) {
return getValidationMessages(error);
}
return msg;
}
function getValidationMessages(error) {
try {
//foreach entity with a validation error
return error.entitiesWithErrors.map(function (entity) {
// get each validation error
return entity.entityAspect.getValidationErrors().map(function (valError) {
// return the error message from the validation
return valError.errorMessage;
}).join('; <br/>');
}).join('; <br/>');
}
catch (e) { }
return 'validation error';
}
Does someone can point me in the right direction?
Thanks in advance.
EDIT:
To reproduce the problem: click on the left sidebar on Transports + recherche avancee + any item in the list + on the right side: clear some inputs (like Numero d'affaire as screenshot below) then click on 'Enregistrer'. Then the save button is called. There I need to check if there are invalid inputs with ko.validation.group but it doesn't work.
回答1:
Some time ago, I posted a helper function that extend observable properties to add validation based on the breeze validators. Using that helper you can achieve the red color on the invalid inputs:
Translate breeze validation messages
I can't help you with the second question, I know that you can customize the validation message but I think that with the default validators you can't set a friendly name to show on the message.
Update:
The first that I do is to create a helper module that exposes the function (updated version):
define([],
function () {
"use strict";
var foreignKeyInvalidValue = 0;
function addValidationRules(entity) {
var entityType = entity.entityType,
i,
property,
propertyName,
propertyObject,
validators,
u,
validator,
nValidator;
if (entityType) {
for (i = 0; i < entityType.dataProperties.length; i += 1) {
property = entityType.dataProperties[i];
propertyName = property.name;
propertyObject = entity[propertyName];
validators = [];
for (u = 0; u < property.validators.length; u += 1) {
validator = property.validators[u];
nValidator = {
propertyName: propertyName,
validator: function (val) {
var error = this.innerValidator.validate(val, { displayName: this.propertyName });
this.message = error ? error.errorMessage : "";
return error === null;
},
message: "",
innerValidator: validator
};
validators.push(nValidator);
}
propertyObject.extend({
validation: validators
});
}
for (i = 0; i < entityType.foreignKeyProperties.length; i += 1) {
property = entityType.foreignKeyProperties[i];
propertyName = property.name;
propertyObject = entity[propertyName];
validators = [];
for (u = 0; u < property.validators.length; u += 1) {
validator = property.validators[u];
nValidator = {
propertyName: propertyName,
validator: function (val) {
var error = this.innerValidator.validate(val, { displayName: this.propertyName });
this.message = error ? error.errorMessage : "";
return error === null;
},
message: "",
innerValidator: validator
};
validators.push(nValidator);
}
propertyObject.extend({
validation: validators
});
if (!property.isNullable) {
//Bussiness Rule: 0 is not allowed for required foreign keys
propertyObject.extend({ notEqual: foreignKeyInvalidValue });
}
}
}
}
return {
addValidationRules: addValidationRules
};
});
Then, I'm defining an initializer for each breeze entity type ( http://www.breezejs.com/documentation/extending-entities ). Example:
define(['app/validatorHelper', 'knockout'],
function (vHelper, ko) {
"use strict";
var constructor = function () {
},
initializer = function indicadorInitializer(entity) {
vHelper.addValidationRules(entity);
};
return {
constructor: constructor,
initializer: initializer
};
});
And finally, somewhere ( I'm doing it on an init function inside my dataservice module ), I'm registering the initializer ( http://www.breezejs.com/documentation/extending-entities ) :
//store comes from: manager = breezeconfig.createManager(),
// store = manager.metadataStore,
store.registerEntityTypeCtor("Palanca", domain.palanca.constructor, domain.palanca.initializer);
I'm doing all of this before fetching the metadata.
I hope that this would help you.
Update 2:
I've found the problem, your version of knockout validation is not the last one.
Inside the downloaded file from: http://ericmbarnard.github.com/Knockout-Validation/ the line: 349 is:
exports.rules[ruleName] = ruleObj;
Inside your file, the equivalent line ( function addAnonymousRule ) is:
ko.validation.rules[ruleName] = {
validator: ruleObj.validator,
message: ruleObj.message || 'Error'
};
I think that with the lastest version should work.
Update 4:
This is the code to save:
vmAddPalanca.prototype.saveChangesCmd = ko.asyncCommand({
execute: function (palanca, complete) {
var validationErrors = ko.validation.group(palanca);
if (validationErrors().length === 0) {
dataservice.saveChanges()
.then(saveChangesSuccess)
.fail(saveChangesFail)
.fin(complete);
} else {
validationErrors.showAllMessages(true);
toastr.error("Debe corregir los errores antes de poder guardar");
complete();
}
},
canExecute: function (isExecuting) {
return !isExecuting && dataservice.hasChanges();
}
});
来源:https://stackoverflow.com/questions/15635958/mark-fields-not-valid-as-red-with-knockout-durandal