backbone.js model validation isValid() returns true for invalid attribute - validation

I was trying to check the validity of individual attributes using isValid method. It is returning true for an invalid attribute. My code is as follows:
person = Backbone.Model.extend({
defaults:{
name:"default name",
age:0
},
initialize:function(){
this.on("invalid",function(model,errors){
console.log(JSON.stringify(errors));
});
},
validate:function(attrs){
errors=[];
if(attrs.age<0){
errors.push({attribName:"age",errorMsg:"age should be grater than 0"});
}
return errors.length>0?errors:false;
}
});
var person1 = new person();
person1.set({
age:-5
});
console.log("checking validity of model:"+person1.isValid());
console.log("checking for validity of age attribute:"+person1.isValid('age'));
isValid() works fine if used to check the validity of the model as a whole and returns false. But when I try to check the age attribute i.e isValid('age') it returns true when it should return false.
isValid() is an underscore.js function, right? Doesn't it support passing an attribute to check for its validity? What am I missing here?

Short version
Model.isValid doesn't accept an attribute name as argument and has to be used on the whole model. If you don't, you're on undocumented territory and you will get weird behaviors.
To check individual attributes, you will have to set up your own mechanism.
Long version, why you get a different value
Model.isValid does in fact accept an (undocumented) options hash as its first argument and it internally forwards this hash to Model._validate via
this._validate({}, _.extend(options || {}, { validate: true }))
trying to set a validate attribute to true. But at this point, options is a string and won't be modified by _.extend. _validate looks like
_validate: function(attrs, options) {
if (!options.validate || !this.validate) return true;
// ...
}
checking if it indeed has to validate the model, options.validate is undefined and your isValid call gets back a true value.

isValid is a backbone API : http://backbonejs.org/#Model-isValid
The reason it is returning true is, the parameter accepted by isValid is an options paramter. It has to be an object.
One of the scenario you use options is :
validate: function(attrs, options) {
if(options.someSpecialCheck) {
// Perform some special checks here
} else {
// Perform some regular checks here
}
}
myModel.isValid({someSpecialCheck: true});

Related

Grails validation on an associated 'hasMany' object

I'm having a validation issue very similar to what is described here
https://schneide.wordpress.com/2010/09/20/gorm-gotchas-validation-and-hasmany/
but with an important difference that I don't have (or want) a List<Element> elements field in my domain. My code is
class Location {
static hasMany = [pocs: LocationPoc]
Integer id
String address
String city
State state
String zip
...
static mapping = {
...
}
static constraints = {
def regEx = new RegEx()
address blank: true, nullable: true, matches: regEx.VALID_ADDRESS_REGEX
city blank: true, nullable: true
state blank: true, nullable: true
zip blank: true, nullable: true
...
}
}
however, if I save/update a location with a bunk POC (point of contact), I get some wild errors. I would like to validate the POC's when I save/update a location, but I'm not exactly sure how. I've tried a few variations of
pocs validator: {
obj -> obj?.pocs?.each {
if (!it.validate()) {
return false
}
}
return true
}
to no avail. Is this possbile without creating a new field on my domain, List<LocationPoc> pocs?
You're close. The issue is you need to target the property you want to validate instead of using the object reference. It should look like this:
pocs validator: { val, obj, err ->
val?.each {
if (!it.validate()) return false
}
}
Validation doesn't automatically cascade through hasMany associations. In order to get free validation, the other side of the relationship needs to belong to Location.
You didn't include your LocationPOC class, but if you modify
Location location
to
static belongsTo = [location: Location]
Then you will get cascading validation when you save your Location object.
If you can't set the belongsTo property on LocationPoc, and need to use the custom validator, the syntax is a bit different than the answer above.
pocs validator: {val, obj ->
val?.inject true, {acc,item -> acc && item.validate()}
}
the three arguement version of validate expects you to add errors to the errorCollection. https://grails.github.io/grails2-doc/2.5.6/ref/Constraints/validator.html
Plus using a return statement inside of .each doesn't work like the above example. It just exits the closure and starts the next iteration. The validator from the other answer was just returning val (the result of val.each is just val)
You need to spin through the entire collection looking for non valid options.

Grails - Domain object doesn't validate correctly

I'm trying to set the date of birth of a person using jQuery Datepicker. However, all I get is that the Property dateOfBirth must be a valid Date.
So, originally, my controller looks like this:
def update(Person personInstance) {
if (personInstance == null) {
// do Something
return
}
if (personInstance.hasErrors()) {
respond personInstance.errors, view: 'edit'
return
}
// do the rest
}
I figured out, that with jQuery I should use a SimpleDateFormat object in order to generate a proper Date object. Nevertheless, even if I directly assign a new Date object to dateOfBirth and subsequently validating the personInstance domain object - like in the following code segment - I still get the Property dateOfBirth must be a valid Date error.
def update(Person personInstance) {
if (personInstance == null) {
// do Something
return
}
// added code
personInstance.dateOfBirth = new Date()
personInstance.validate()
// added code
if (personInstance.hasErrors()) {
respond personInstance.errors, view: 'edit'
return
}
// do the rest
}
Thank you for any help :)
The reason why you are still seeing errors is because validation is automatically called after binding your command/domain object when the method is called.
Use personInstance.clearErrors() before calling personInstance.validate() manually to clear out any existing binding/validation errors. You can see more about this in the documentation.

Backbone.js - validating model constructor parameters

I want to do simple thing with a model:
use constructor parameters if they are valid (but not just assign them, I have to map them before as they are in a different format)
in other case, use defaults
What's the recomended solution for this?
You can achieve this by calling isValid() in initialize. If it's valid, then proceed as normal; otherwise, clear the model and reset it with the default values:
initialize: function() {
console.log("initializing model...");
if (!this.isValid()) {
console.log("Model is not valid, using defaults");
this.clear({ silent: true });
this.set(this.defaults, { silent: true });
}
console.log("Model is valid");
},
See this working demo.
Edit
It's possible to use objects in the model constructor, for example:
var model = new Backbone.Model({
title: "test",
hsa: {
h: 120,
s: "100%",
a: "50%"
}
});
You could also specify it as hsa: "120, 100%, 50%" or something, and convert that value to an object in the constructor.
See here.

Validate other field without causing infinite loop

I have a situation where I am creating an unobtrusive validator that must validate that another field is required only if the validated field is not empty (and vice versa). The problem is that there are some edge cases where the other field does not re-validate, and I would like to force it to revalidate itself without causing an infinite loop.
My validation method looks like this:
$.validator.addMethod("jqiprequired", function (value, element, params) {
if (!this.optional(element) || (this.optional(params) && this.optional(element))) {
return true;
}
return false;
});
params is my other field (both are textboxes). If both are empty, it passes, if both have values, it passes. It only fails if only one has a value.
This works fine, except that if one field is empty, and another has a value, then you delete the value from the field with a value, the empty field is not revalidated (because it's value has not changed).
I tried doing this:
if (!this.optional(element) || (this.optional(params) && this.optional(element))) {
$('form').validate().element(params);
return true;
}
But this causes an infinite loop because each time it passes, it calls the other.
How can I cause the other field to validate, without itself calling the original field?
Instead of adding an attribute to each field, try adding a variable jqip_validating in the script where you are adding this validation method. Then, change your validation as follows:
var jqip_calledFromOtherValidator = false;
if (jqip_validating) {
jqip_validating = false;
jqip_calledFromOtherValidator = true;
}
if (!this.optional(element) || (this.optional(params) && this.optional(element))) {
if (!jqip_validating && !jqip_calledFromOtherValidator) {
jqip_validating = true;
$('form').validate().element(params);
}
return true;
}
In order for the other validator to be called, both conditions must be satisfied, and they can only be satisfied when the first validator invokes the second validator.
You can add a is_validating attribute to each fields so that, if it's on you skip the validation and if not, you set it to true, do your validation and then clear it.

How to ensure a boolean field to be set in Grails?

I want to ensure that one of two form fields representing a boolean value is checked. But there is no appropriate constraint to do this. nullable: false does not work.
class Organisation {
Boolean selfInspecting
static constraints = {
selfInspecting(nullable: false)
}
}
How can I check whether one of the two fields is checked or not?
Perhaps the simplest approach is to use a form that ensures a value is picked. As such, creating a radio buttons rather than checkboxes is a better solution. It would directly represent your intent as well.
You can also check this in the Controller, e.g.
if (params.checkBox1 != 'on' && params.checkBox2 != 'on')
flash.error = 'At least one value must be checked.'
return ...
you can write your own custom validator.
something like
selfInspecting(validator: {val, obj -> /*test selfInspecting here*/})
EDIT -- in response to the other answer -- you can handle this on the form, but you should also handle it on the server.
ANOTHER EDIT -- It was suggested in a comment that you might want to validate one of two fields on your Domain class. This is also easily accomplished with a custom validator. With the signature above for the custom validator closure, the val is the value selfInspecting, and obj is the domain object instance. So you could have
{ val, obj ->
if (val == null) return false // if you want to ensure selfInspecting is not null
else return true
... or ...
// if you want to check that at least 1 of two fields is not null
def oneOrTheOther = false
if (obj.field1 != null || obj.field2 != null)
oneOrTheOther = true
return oneOrTheOther
}

Resources