I am using VS 2010 with MVC 3 and unobtrusive validation. I am attempting to create a custom range validator to includes warnings where input values are acceptable but unexpected. (I have working functionality to submit the values with wanings by using the ignore option of the form validator)
The unobtrusive component is:
// The adapter to support ASP.NET MVC unobtrusive validation //
$.validator.unobtrusive.adapters.add('rangewithwarning', ['min', 'max', 'wmin', 'wmax', 'warning'],
function (options) {
options.rules['rangewithwarning'] = {
min: options.params.min,
max: options.params.max,
wmin: options.params.wmin,
wmax: options.params.wmax,
warning: options.params.warning
};
options.messages['rangewithwarning'] = options.message;
});
I have Googled extensively on dynamic error messages which seem to come down to three methods but none of these allow me to display the optional error message. These are:
Returning the error message
// The validator function
$.validator.addMethod('rangewithwarning', function (value, element, params) {
if (!value) {
return true; // not testing 'is required' here!
}
var intValue = parseInt(value);
// set logic here
if (intValue >= params.wmin && intValue <= params.wmax) {
// OK within both actual and range warning
return true;
}
if (params.min <= intValue && intValue <= params.max) {
// outside warning but within allowed range - show warning
return params.warning;
}
return $.validator.messages.rangewithwarning;
});
Use showErrors
// The validator function
$.validator.addMethod('rangewithwarning', function (value, element, params) {
if (!value) {
return true; // not testing 'is required' here!
}
var validator = this;
var intValue = parseInt(value);
// set logic here
if (intValue >= params.wmin && intValue <= params.wmax) {
// OK within both actual and range warning
return true;
}
if (params.min <= intValue && intValue <= params.max) {
// outside warning but within allowed range - show warning
var errors = new Object();
errors[element.name] = params.warning;
validator.showErrors(errors);
}
return false;
});
Return an additional parameter from a messager function
None of these worked although when stepping through the second one the optional message was shown briefly then overwritten.
I'm clearly missing something obvious but cannot see what it is.
Thanks in advance.
Found a solution which was to use the standard range attribute and then follow it with my new warn only attribute
(function ($) {
// The validator function
$.validator.addMethod('rangewarning', function (value, element, params) {
var localElement = $(element);
localElement.siblings("span").removeClass("warningOnlyDataOK")
localElement.removeClass("warningOnlyDataOK")
if (!value) {
return true; // not testing 'is required' here!
}
var intValue = parseInt(value);
// set logic here
if (intValue >= params.wmin && intValue <= params.wmax) {
// OK within both actual and range warning
return true;
}
// set display and ignore class items here etc
localElement.siblings("span").addClass("warningOnlyDataOK")
localElement.addClass("warningOnlyDataOK")
return false;
});
// The adapter to support ASP.NET MVC unobtrusive validation //
$.validator.unobtrusive.adapters.add('rangewarning', ['wmin', 'wmax'],
function (options) {
options.rules['rangewarning'] = {
wmin: options.params.wmin,
wmax: options.params.wmax
};
options.messages['rangewarning'] = options.message;
});
} (jQuery));
Where the class warningOnlyDataOK is used to both display a different style error message and to ignore that validation on save.
Related
I am getting an error while setting global variable flag inside function.
Global variable declaration
var flag = false;
Function to validate textbox
//To validate Product Name field
function Name() {
var pName = document.getElementById('addPName').value;
if (pName == "") {
$('#productNameError').text('Product Name is required');
flag = false;
}
else {
$('#productNameError').text('');
flag = true;
}
}
Function to validate quantity
//To validate Product Quantity Field
function Quantity() {
var pQty = document.getElementById('addPQty').value;
if (pQty != "") {
var regex = /^[1-9]\d*(((,\d{3}){1})?(\.\d{0,2})?)$/;
if (regex.test(pQty)) {
$('#productQtyError').text('');
flag = true;
}
else {
$('#productQtyError').text('Enter Quantity of the Product');
flag = false;
}
}
else {
$('#productQtyError').text('Quantity is required');
flag = false;
}
}
//Validation Summary
function validate() {
if (flag == true) {
$('#validationSummary').text('');
return true;
}
else {
$('#validationSummary').text('Please fill out required fields.');
return false;
}
}
I am calling first two functions on onfocusout event of textbox and calling validate() function on button click. The problem which I am facing is: inside the Quantity() flag is not getting set to false. Although the field remains blank,record gets inserted.
if you are getting flag=true in validate() then you may be calling Quantity() first ,it will set flag false then Name() which will set flag to true so It bypassed validate() function.
This is not the correct way, you are trying to achive validation. Consider scenario, when user have entered the correct value in first filed, flag will be set to true with the fact that second field is empty amd form will be submitted and hold true vice versa.
If want to achive by this way, keep as many flag variables as the number of fields amd chech all those variable inside validate.
Or, use '.each' to iterate each element and validate it and keep appending validation mesages to dom object.
Thanks
Don't use Global Variables
You're going to have a bad time if you use global variables, you can use the revealing module pattern to encapsulate some of the messiness
Would suggest something like this :
var app = app || {};
app.product = app.product || {};
app.product.validate = app.product.validate || {};
app.product.validate.isValid = false;
app.product.validate.name = function(){
var pName = document.getElementById('addPName').value;
if (pName == "") {
$('#productNameError').text('Product Name is required');
app.product.validation.flag = false;
} else {
$('#productNameError').text('');
app.product.validation.flag = true;
}
}
app.product.validate.quantity = function() {
var pQty = document.getElementById('addPQty').value;
if (pQty != "") {
var regex = /^[1-9]\d*(((,\d{3}){1})?(\.\d{0,2})?)$/;
if (regex.test(pQty)) {
$('#productQtyError').text('');
app.product.validate.flag = true;
} else {
$('#productQtyError').text('Enter Quantity of the Product');
app.product.validate.flag = false;
}
} else {
$('#productQtyError').text('Quantity is required');
app.product.validate.flag = false;
}
}
console.log is Your Friend
Try putting a console.log inside some of those methods, what I am guessing your issue is is that something is being called out of the order you expect and setting the flag to a value you aren't expecting.
Can do console.log statement like this console.log if you open up your developer console should show you the output from the console
Current I have the following custom rules to validate fields of my form.
Rules
$scope.validator = $("#frmPreregistration").kendoValidator({
rules: {
varifySsn: function (input) {
var ret = true;
if (input.is("[name=last4Ssn]") && $scope.Last4DigitsSsn != undefined ) {
ret = $scope.validateSsnLast4Digit();
}
return ret;
},
varifyDob: function (input) {
var ret = true;
if (input.is("[name=dob]") && $scope.DateOfBirth != undefined ) {
ret = $scope.validateDateOfBirth();
}
return ret;
},
varifyZipCode: function (input) {
var ret = true;
if (input.is("[name=zipCode]") && $scope.ZipCode != undefined ) {
ret = $scope.validateZipCode();
};
return ret;
}
},
messages: {
varifySsn: $scope.resources.SsnLast4DigitDoesNotMatch,
varifyDob: $scope.resources.DobNotMatchWithSelectedUserType,
varifyZipCode: $scope.resources.ZipCodeNotMatchWithSelectedUserType,
}
}).data("kendoValidator");
I am validating the form whenever user enters a value in any of the field in the form by $scope.validator.validate()
This is resulting in firing the rules for all the fields even before the user enters any value into it.
Question
Is there any possibility that I can run a particular validation rule at a time or run validation for a particular field?
You can use validateInput for specific element.
Example:
$scope.validator.validateInput($("input[name=dob]"));
to hide invalid message you can use hideMessages function
$scope.validator.hideMessages();
How to get value of var total in message,
and also i tried declare inside function but it gives undefined variable
var total = '';
$.validator.addMethod("valueNotEquals", function (value, element, arg) {
var fund_old = $("#current_fund").val();
var fund_new = $("#new_fund").val();
total = parseFloat(9999999999.999999) - parseFloat(fund_old);
if (parseFloat(fund_new) <= parseFloat(total)) {
return true;
} else {
return false;
}
return true;
}, 'sry sktiman' + total + 'is remaining value');
In result i am getting blank value of total
According to the documentation for jQuery.validator.addMethod() you can use jQuery.validator.format() which generates a function that receives the arguments to the validation method and returns a string message, so creating a function that ignores any arguments and returns a string should work:
var total = '';
$.validator.addMethod("valueNotEquals", function (value, element, arg) {
var fund_old = $("#current_fund").val();
var fund_new = $("#new_fund").val();
total = parseFloat(9999999999.999999) - parseFloat(fund_old);
if (parseFloat(fund_new) <= parseFloat(total)) {
return true;
} else {
return false;
}
return true;
}, function() {return 'sry sktiman' + total + 'is remaining value'});
EDIT
The fiddle for this solution can be found here (thanks to Sparky for providing the code).
The optional parameters can be used inside the message.
The third argument, the optional parameters, (you call it arg) can be represented within your code as arg[0], arg[1], etc.
Then the corresponding values can be used in your message as {0}, {1}, etc.
Do your calculation external to .addMethod() and pass the value in using the arg argument.
$.validator.addMethod("valueNotEquals", function(value, element, arg){
var fund_old= $("#current_fund").val();
var fund_new =$("#new_fund").val();
// do this calculation where the rule is declared. See 'validate()'
//total = parseFloat(9999999999.999999) - parseFloat(fund_old);
if(parseFloat(fund_new) <= parseFloat(total)){
return true;
} else {
return false;
}
return true;
},'sry sktiman {0} is remaining value');
Since you didn't show your .validate() or the HTML markup, maybe something like this...
$('#myform').validate({
rules: {
fund_old: {
// your rules
},
fund_new: {
valueNotEquals: function() {
return ($parseFloat(9999999999.999999) - parseFloat($("#current_fund").val()));
}
}
}
});
Crude demo: http://jsfiddle.net/eZm7x/
Just add this line function() {return 'sry sktiman' + total + 'is remaining value'} as your second argument, you can easily use this variable
var total = '';
$.validator.addMethod("valueNotEquals", function (value, element, arg) {
//Your default code here
}, function() {return 'sry sktiman' + total + 'is remaining value'});
Try,
var total = '';
$.validator.addMethod("valueNotEquals", function(value, element, arg){
var fund_old= $("#current_fund").val();
var fund_new =$("#new_fund").val();
total = parseFloat(9999999999.999999) - parseFloat(fund_old);
if(parseFloat(fund_new) <= parseFloat(total)){
return true;
}else{
return false;
}
return true;
},'sry sktiman'+ (parseFloat(9999999999.999999) - parseFloat($("#current_fund").val())) + 'is remaining value');
In addMethod Documentation says: "Add a custom validation method. It must consist of a name (must be a legal javascript identifier), a javascript based function and a default string message."
So, you are adding a custom validation function to plugin, and NOT executing that function.
Try to set a field with your custom validation and fill that field to run your custom function. Just AFTER that check total var value.
I have a function that simply validates forms (for old browsers). The function works just fine except that I have to pass the parameters every time I call this function, where in fact I already specified the default parameters in 'config'.
So by logic, If I called the function as: validateMe(); it should run as validateMe({requiredClass: '.required', verifiedClass: 'invalid'});
but unfortunately calling the function without parameters doesn't work correctly ( in my case the form triggers the submission event) (it doesn't reach return false).
so what is missing in the code to run the function with the default settings??
function validateMe(vform, settings) {
var vform, //form name or id
config = {
'requiredClass': '.required',
'verifiedClass': 'invalid'
};
if (settings) {
$.extend(config, settings);
}
$(vform).on('submit', function(){
var inputs = $(this).find(config.requiredClass),
required = [];
for (i=0; i < inputs.length; i++) {
if (inputs[i] != null) {
if ($(inputs[i]).val().replace(/^\s+|\s+$/g, '') == '') {
required.push($(inputs[i]).index());
}
}
}
if (required.length > 0) {
$(this).find('input').removeClass(config.verifiedClass);
for(n=0;n<required.length;n++) {
$(inputs[n]).addClass(config.verifiedClass);
}
return false;
}
});
}
Any help?
Thanks.
function validateMe(vform, settings) {
this.vform = vform || 'default',
this.setting = 'whatever',
this.private = ''
}
var newInstance = new validateMe();
now you have an instance of it, so you can define it as you go.
Normally in my backbone validation, I have a crazy amount of if() statements, as I've seen in many other code samples as well. Validation is pretty much a crap shoot in backbone; however, the if() way seems to work. I want to clean up the code a bit and wrote some code that does return error which should stop backbone from saving the attribute, but it doesn't!
OLD Code that works
validate : function(attr){
if(attr.firstName){
var defaultValue = 'first name',
value = attr.firstName.toLowerCase();
if(value == defaultValue){
return 'error';
}
}
}
NEW code that doesn't work
//My default strings from another place
MyApp.strings.defaults = {
firstName : 'first name'
}
//Model Validate function
validate : function(attr){
jQuery.each(attr, function(key, value){
var defaultValue = MyApp.strings.defaults[key];
if(defaultValue){
defaultValue = jQuery.trim(defaultValue.toLowerCase());
if(value == defaultValue){
console.log(value, defaultValue); //fires, and outputs both as being the same
return 'error';
}
}
});
}
Are you not allowed to loop over the attributes in Backbone validation?
You are not returning any value from the validate method, you were returning 'error' from the each() callback method, not from validate
//My default strings from another place
MyApp.strings.defaults = {
firstName : 'first name'
}
//Model Validate function
validate : function(attr){
var error;
jQuery.each(attr, function(key, value){
var defaultValue = MyApp.strings.defaults[key];
if(defaultValue){
defaultValue = jQuery.trim(defaultValue.toLowerCase());
if(value.toLowerCase() == defaultValue){
console.log(value, defaultValue); //fires, and outputs both as being the same
error = 'error';
return false;
}
}
});
return error;
}