PDA

View Full Version : Conditional fields validations



sim4life
31 Jan 2011, 10:45 AM
Hi I'm looking for a similar solution as described in the following thread for ExtJS
http://www.sencha.com/forum/showthread.php?118555-Solved-Conditional-field-validation&highlight=validation

Basically, I have 2 fields, a selectfield and a datefield. Both are optional but if the user picks some value for selectfield then he must also pick a date in the datefield.
My partially written code is



Ext.regModel('Todo', {
fields: [
{name: 'id', type: 'int'},
{name: 'title', type: 'string'},
{name: 'due_at', type: 'date'},
{name: 'remind_before', type: 'string'},
{name: 'completed_at', type: 'string'},
{name: 'todo_id', type: 'int'},
{name: 'cl_state', type: 'string'},
{name: 'action', type: 'string'}
],
validations: [
{type: 'presence', name: 'title', message: "Title is required"},
{type: 'presenceDueDate', name: 'remind_before'}
]
});




Ext.apply(Ext.data.validations,{
presenceDueDateMessage: 'Due Date is missing',
presenceDueDate: function(config, value) {
if(value == "") {
return true;
} else {
console.dir(this);
// if()//validate presence of due date
return false;
}
}
});


I think I need to write the custom validator function like presenceDueDate. In the second last line of code // if presence of due date field is validated then I return true otherwise, u guessed it, false

Secondly, the validations option of a model takes an array with its items' options as name, type, message, list etc... Exactly where in the documentation/source code are all these options listed [In case I don't have to write a custom validator?]

Anyone with any help plz!

krause
16 Jun 2011, 8:24 AM
I think you are in the right path, the only problem is that your custom validation function (i.e. presenceDueDate) only receives config and value as arguments. You need access to the rest of the record/model in order to peek into other fields. For this you might have to override the validate method in Ext.data.Model in order to pass the model, for example:


Ext.override(Ext.data.Model, {
/**
* Validates the current data against all of its configured {@link #validations} and returns an
* {@link Ext.data.Errors Errors} object
* @return {Ext.data.Errors} The errors object
*/
validate: function() {
var errors = new Ext.data.Errors(),
validations = this.validations,
validators = Ext.data.validations,
length, validation, field, valid, type, i;

if (validations) {
length = validations.length;

for (i = 0; i < length; i++) {
validation = validations[i];
field = validation.field || validation.name;
type = validation.type;
valid = validators[type](validation, this.get(field), this);

if (!valid) {
errors.add({
field : field,
message: validation.message || validators[type + 'Message']
});
}
}
}

return errors;
}
});

and your custom validator now would recieve a third argument which is the model instance you are validating, so you could take a look at other fields, for example model.get('due_at') and do whatever comparison you need.

Hope this helps.

[Applies to Sencha Touch 1.1.0]

krause
16 Jun 2011, 8:34 AM
Additionally, since Ext.data.validations is a singleton you might want to consider a generic "custom" validator type which will call the specified "validator" method when required like this:


Ext.apply(Ext.data.validations , {
custom : function(config, value, model) {
return config.validator.apply(this, arguments);
}
});



myModel = Ext.regModel('myModel', {
fields : [ {
name : 'tel',
type : 'string'
}, {
name : 'email',
type : 'string'
}],

validations : [ {
field : 'tel',
type : 'custom',
message : 'Either phone or mail are required',
validator : function(config, value, model) {
if ( Ext.isEmpty(value) && Ext.isEmpty(model.get('email')) ) {
return false;
}
return true;
}
}]
});

This way, if you have several conditional validations in your app, you don't pollute the Ext.data.validations singleton. Notice that this will still need the override to the validate method of Ext.data.Model described in the previous post in order to get access to the rest of the model.

Just an idea.

bwg
28 Jun 2011, 7:42 PM
This method works very well. Thanks!