Advanced Data Validation Using ExtJs
While working on my personal project tonight I finally got around to going over some of the new examples in the ExtJs documentation. In this case they are demonstrating having a form with a password field, and a confirmation password field, and how you can validate that the second password entered is the same as the first. That’s fine and dandy, but I did need it to do a little more. I need this validation to verify that the entered password is at least five characters, and contains at least one number or special character from a specific set.
So here is an excerpt of the form definitions. I have the first password box, and a second for confirmation. Notice the “vtype” is set to “password”. This is key.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | { fieldLabel: 'Password', id: 'password', name: 'password', allowBlank: false, xtype: 'textfield', inputType: 'password', vtype: 'password', width: 200, maxLength: 64 }, { fieldLabel: 'Confirm', id: 'passwordConfirm', name: 'passwordConfirm', xtype: 'textfield', inputType: 'password', vtype: 'password', allowBlank: false, width: 200, maxLength: 64, initialPasswordField: 'password' } |
Now, prior to this you need to define the behavior for the password validation. This is done by vtypes. In ExtJs a vtype is basically an object with custom data validation functions that return true or false upon success of validation. They also include a message to display in a QuickTip when a data validation error occurs. Here is the code I used to validate the passwords according to the rules mentioned above.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Ext.apply(Ext.form.VTypes, { password: function(value, field) { if (field.initialPasswordField) { var pwd = Ext.getCmp(field.initialPasswordField); this.passwordText = 'Confirmation does not match your intial password entry.'; return (value == pwd.getValue()); } this.passwordText = 'Passwords must be at least 5 characters, containing either a number, or a valid special character (!@#$%^&*()-_=+)'; var hasSpecial = value.match(/[0-9!@#\$%\^&\*\(\)\-_=\+]+/i); var hasLength = (value.length >= 5); return (hasSpecial && hasLength); }, passwordText: 'Passwords must be at least 5 characters, containing either a number, or a valid special character (!@#$%^&*()-_=+)', }); |
If you aren’t familiar with Ext.apply this is a function that takes two objects and combines them. And here is no exception. We are combining a new object with OUR definition of the password validation with the existing VTypes object.
If you noticed the property “initialPasswordField” in the confirmation field, you’ll see that the first thing our password validation function does is check to see if the form field has this property. If it does that means we are validating data for the confirmation field, and we want to make sure it matches the first password box.
If the current field being validated is not the confirmation field, but instead the initial password field, I am defining two variables: hasSpecial, and hasLength. These are the two criteria I am testing against. The hasLength is obvious; true or false if the value is greater than or equal to five characters in length. The hasSpecial is simply a regular expression that checks to see if the value has at least one number, or one character in the list: !@#$%^&*()-_=+.
Also notice the passwordText property. This is the default message to use when the data validation fails. You will also see that I am changing the password text based on which field you are working with when the data validation occurs.
I, for one, am quite excited about the power and flexibility of how data validation and vtypes works with ExtJs. Cheers, and happy coding!





Adam,
In the above example, if the password is entered and then confirmed, and then the user goes back to the first to edit it, the validation fails to notice they no longer match.
Eric
Adam,
This works better (but the regex needs to be added back in.)
Ext.apply(Ext.form.VTypes, { password: function(value, field){ var valid = false;
},
passwordText: ‘Passwords do not match.’, });
With the following items:
Regards,
Eric
Thanks for pointing that out. Nice catch.
Hey guys, I’ve found this one when I needed to check my password fields for matching.
So I wrote similar to yours:
[code] Ext.apply(Ext.form.VTypes, { match: function(value, field){ if (field.matchField) { var form = field.findParentByType('form'); var f; if (form && form.getForm() && (f = form.getForm().findField(field.matchField))) { if (value == f.getValue()) return true; // else if (field.matchInvalidText) this.matchText = field.matchInvalidText; f.markInvalid(this.matchText); } return false; }
}); [/code]
Useage: [code] { fieldLabel: 'New password', xtype: 'textfield', anchor: '100%', inputType: 'password', name: 'password', vtype: 'match', matchField: 'password2', matchInvalidText: 'Passwords do not match' }, { fieldLabel: 'Confirm password', xtype: 'textfield', anchor: '100%', inputType: 'password', name: 'password2', vtype: 'match', matchField: 'password', matchInvalidText: 'Passwords do not match' } [/code]
The benefit is: * It doesn’t require fields to have IDs (which is importaint if you may have many password fields at once). Both fields must be within the same FormPanel. * customizable mismatch text.
Cheerz ^_^
… The markup is screwed… well, here is updated code anyway:
Ext.apply(Ext.form.VTypes, { match: function(value, field){ if (field.matchField) { var form = field.findParentByType(‘form’); var f; if (form && form.getForm() && (f = form.getForm().findField(field.matchField))) { if (value == f.getValue()){ f.clearInvalid(); return true; } // else if (field.matchInvalidText) this.matchText = field.matchInvalidText; f.markInvalid(this.matchText); } return false; }
});