Skip validation of model attribute using Backbone.Validation - javascript

I have a view that is rendered dynamically. It may have some inputs or may not have.
After a user fills everything and tries to send data I call this.model.isValid(true) ( or this.model.isValid() ) and it returns false even if the data from inputs is valid.
I think the cause is Backbone Validation tries to validate attributes of inputs we did not render.
Is there any solution to skip model attributes if we have no sticked elements of a view?
UPDATE:
My model is similar to this:
MyApp.module("RecordModel", function (RecordModel, MyApp, Backbone) {
RecordModel.recordModel = Backbone.Model.extend({
validation: {
inn: {
pattern: 'inn',
msg: MyApp.messages.inn
},
bik: {
pattern: 'bik',
msg: MyApp.messages.bik
},
uin: {
pattern: 'uin',
msg: MyApp.messages.uin
},
sum: {
pattern: 'sum',
msg: MyApp.messages.sum
}
}
});
});
Bindings:
bindings: {
'#uin': {
observe: 'uin',
setOptions: {
validate: true
},
events: MyApp.Validation.events.inputEvents
},
'#bik': {
observe: 'bik',
setOptions: {
validate: true
},
events: MyApp.Validation.events.inputEvents
},
'#inn': {
observe: 'inn',
setOptions: {
validate: true
},
events: ParkingMate.Validation.events.inputEvents
},
'#sum': {
observe: 'sum',
setOptions: {
validate: true
},
events: MyApp.Validation.events.inputEvents
}
}
So for some reason we din't render #sum input for instance. As we haven't it got in our DOM, it doesn't exists in RecordModel, but backbone still tries to validate it. Or if we have this input in our DOM, everything works fine.

How can I allow empty values but still validate if the user enters something?
By default, if you configure a validator for an attribute, it is
considered required. However, if you want to allow empty values and
still validate when something is entered, add required: false in
addition to other validators.
validation: {
value: {
min: 1,
required: false
}
}
If you can't let empty values (like at creation), Backbone.validation overrides isValid adding features to the default behavior. What's interesting is the array parameter we can pass:
// Check if name and age are valid
var isValid = model.isValid(['name', 'age']);
With this, we can then validate only the fields that exist within the model at the moment:
model.isValid(_.keys(model.attributes));

Related

knockout validation inner observable validation is not triggred

I have the following JS object:
var form= function () {
var self = this;
self.Name = ko.observable().extend({
required: {
message: 'Name is required.'
}
});
self.Manager = ko.observable().extend({
required: {
message: 'Manager is required.'
}
});
self.Email = ko.observable().extend({
required: {
message: 'Email is required.'
},
email: {
message: 'Entered Email is not valid.'
}
});
self.Players = ko.observableArray([]);
}
Players array in the above JS object is populated using the following JS object using the new Player() syntax:
var Player = function () {
var self = this;
self.FirstName= ko.observable().extend({
required: {
message: 'Player First Nameis required.'
}
});
self.LastName= ko.observable().extend({
required: {
message: 'Player Last Name is required.'
}
});
}
And I have used the following settings for knockout-validation library:
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: false,
parseInputAttributes: true,
messageTemplate: null,
decorateInputElement: true,
errorElementClass: 'error',
grouping: {
deep: true,
observable: true
}
}, true);
I am using the viewModel.errors.showAllMessages() to display all the error messages in the view model. The problem I am facing is that the validations for the player object are not getting triggered as it is present inside the Form object. I have even set the deep property to true but even that is not working, what could be the issue?
The short answer is you will need to use { live: true } to track errors from objects that are added to observable arrays.
Longer answer:
I've used Jeroen's fiddle as a starting point and assumed that what you want is to show error messages for all validatable observables of all the players.
Use ko.validation.group(vm, options) to get the list of errors. It is the returned object (a computed observable returning an array of errors) that exposes showAllMessages function.
By default it will not perform a deep traversal of the supplied view model, so you will only get errors for Name, Manager, and Email properties (as I assume you are getting currently).
To make it use deep traversal you can supply { deep: true } option. That should give you errors for all players that were in the array at the time group function is called.
If you want it to also track objects added to observable arrays (players in your case) after group function is called, you can use { live: true } option. It will create a subscription on the array and update the list of errors each time the array is modified. Here is the issue that added it: https://github.com/Knockout-Contrib/Knockout-Validation/pull/223
Below is the relevant snipped and here is the fiddle:
https://jsfiddle.net/2a7t72be/1/
var form = function () {
var self = this;
self.showErrors = function(){
self.errors.showAllMessages();
};
// ...
self.Players = ko.observableArray([]);
self.errors = ko.validation.group(self, { deep: true, live: true });
}
PS. You can of course configure grouping options when calling validation.init (just do it before your call to group).

How to add a complex object to model of each angular-formy type when validated?

Say I have a custom angular-formly type that extends a input type.
Lets call it user.
Before the form gets filled in model = {}.
Once its filled in and valid, I would like to have this result
model = {
user:{
name:"TestName" //The value of the input
someCustomData: "Not part of the form"
someMoreMetaData: "Also not part of the from"
}
}
The resulting model having appended arbitrary meta-data once user entered a valid name. Thus creating a "user specific model"
So basically, I want my validation function to push the result to the model.
How would I approach this, for the key has to be bound to a property of a object that will only exist once validation returns true.
{
key: //what do I bind to?
type: 'USER',
templateOptions: {
required: true,
type: 'text'
},
validators:{
isValid: function($viewValue, $modelValue, scope){
var value = $modelValue || $viewValue;
if (validateName(value)){
scope.model.user = { name: viewValue, date:....}
return true;
}
}
}
}
If possible, please nudge me in the right direction..Still pretty novice.
$scope.user
{
'name':'TestName',
'someCustomData': 'Not part of the form',
'someMoreMetaData': 'Also not part of the from'
}
You should add a watch validation and act when valid:
scope.$watch('myForm.myInput.$valid', function(validity) {$scope.user.custom data ="blabla"})

meteor autoform custom validation not reactive

I'm trying to use a custom validation function for a field defined in a simpleSchema, however the error message does not render on the field.
num: {
type: Number,
label: "Number",
min: 1,
decimal: false, // unnecessary as this is default for Number, but for future reference
autoform: {
group: "Info",
defaultValue: function() {
//#TODO - default to next number for logged in user
return 5;
}
},
custom: function () {
Collection.simpleSchema().namedContext("addNumberForm").addInvalidKeys([{name: "num", type: "numNotUnique"}]);
}
},
I've defined a custom error message for it
SimpleSchema.messages({numNotUnique: "This number has already been entered"});
When I submit the form I can confirm that the custom function executes, but nothing changes in the UI for that field indicating the error. The context name "addNumberForm" I got from the SimpleSchema.debug = true; setting and seeing what was thrown for other fields with default validation.
What am I missing here?
After much trial and error I've figured it out.
The simpleSchema named context is only necessary if manually validating using simpleSchema by itself. Autoform takes care of this, and the custom function can return a simple string that defines the error.
num: {
type: Number,
label: "Number",
min: 1,
decimal: false, // unnecessary as this is default for Number, but for future reference
autoform: {
group: "Info",
defaultValue: function() {
//#TODO - default to next number for logged in user
return 5;
}
},
custom: function () {
// some check
return 'numNotUnique'; // return our error
}
},

jQuery required( dependency-expression ) is not working properly

I am using jquery validation plugin. When I was using required( dependency-expression ) i noticed that
required( dependency-expression ) are not working properly. as mentioned that i tried for
$("#flight_availability").validate({
rules: {
Trip: { required: true },
DepartDate: { required : "#OneTrip:checked" },
Origin: { required:"#OriginId:blank" }
},
});
In the above mentioned code the code DepartDate: { required : "#OneTrip:checked" }, works fine but Origin: { required:"#OriginId:blank" } does not work.
Whats wrong with the code? I used firebug. It did not show any errors. even used validation debug option too, but :(
As per OP's comments:
"even if OriginId is empty(blank), it validates it as true"
Yes, that is exactly how you programmed it.
Origin: {
required: "#OriginId:blank"
}
The above code is saying that the Origin field is only required when the #OriginId field is left blank. Using #OriginId:filled, this logic is saying that the Origin field must remain empty if the #OriginId is filled in. If that's not exactly correct, then you can use the :blank selector instead.
http://jsfiddle.net/xMAs5/
If you want the opposite behavior then use the :filled selector instead.
Origin: {
required: "#OriginId:filled"
}
http://jsfiddle.net/xMAs5/1/
Otherwise, here is a demo using a custom method called empty that works as per your comment: "So if OriginId is empty means Origin value (anything) is invalid."
$(document).ready(function () {
$.validator.addMethod('empty', function (value, element) {
return (value === '');
}, "This field must remain empty!");
$("#flight_availability").validate({
rules: {
Trip: {
required: true
},
DepartDate: {
required: "#OneTrip:checked"
},
Origin: {
empty: {
depends: function (element) {
return $("#OriginId").is(":blank")
}
}
}
}
});
});
DEMO: http://jsfiddle.net/Ab8bT/
It might be the jQuery puesdo selector try using :empty instead of :blank.

backbone-forms.js - can i set minlength like in jQuery validate or have i to validate on my own after rendering the backbone form?

here is my form: can i set validation rules inside this definition or have i
to validate over it by hand with conditional statements or is something like this already build in?
i would like to set for learning purposes the minlength to 20 without conditionals of my own.
or shall i extend the plugin by including them in the plugin file?
var form1 = new Backbone.Form({
schema: {
country: { type: 'Select', options: ['UK', 'USA'] },
city: { type: 'Select', options: cities.UK },
message: { validators: ['required', 'message'] }
}
}).render();
You can define a minimum length rule as a regular expression:
message: { validators: [ 'required', /.{20,}/ ] }
All the validation options are documented here.

Categories

Resources