Hi all,
I've just posted Remote Field Validation Plugin for Form Fields.
You can see demo here: http://aariadne.com/rvalidate
Enjoy!
Hi all,
I've just posted Remote Field Validation Plugin for Form Fields.
You can see demo here: http://aariadne.com/rvalidate
Enjoy!
Jozef Sakalos, aka Saki
Education, extensions and services for developers at new http://extjs.eu
News: Grid MultiSearch Plugin, Grid MultiSort Plugin, Configuring ViewModel Hierarchy
Very nice plugin! This is very useful.
p.s.
I think the following piece of code can be removed from the the example source code. You don't use the function anywhere. In the button configuration you specify a more complete and anonymous function. (Or I just overlooked something)
Code:var submit = function() { form.getForm().submit({url:'echo.php', method:'post'}); }
Yes, you're right. It's some stray code. I'll remove it.
Jozef Sakalos, aka Saki
Education, extensions and services for developers at new http://extjs.eu
News: Grid MultiSearch Plugin, Grid MultiSort Plugin, Configuring ViewModel Hierarchy
Hi.
It's very useful plugin, thanks.
But I'm little upgrate your plugin:
- Changed validation logic
- Added loading icon
- Added Valid icon.
Tested in IE6, Opera 9.02, FireFox 2.0.0.10
Sory for my english, i hope i wrote understandable.
Don't be too strict - i'm using ExtJS not long yet.
And i'm not profi in css rules. And i don't like how i calculate left position of inserted div in function getVlmLeftPos. Please hwo can show me the better way to solve this problem.
Now plugin looks so:
and css:Code:Ext.ux.plugins.RemoteValidator = { init:function(field) { // save original functions var isValid = field.isValid; var validate = field.validate; var markInvalid = field.markInvalid; // apply remote validation to field Ext.apply(field, { remoteValid:false, requestExecuting: true, isValid:function(preventMark) { return isValid.call(this, preventMark) && !this.requestExecuting && this.remoteValid; }, validate:function() { if(!validate.call(this)) { this.remoteValidationTask.cancel(); this.hideLoadingMask(); return false; } if (this.requestExecuting) { return false; } else { if(this.remoteValid) { this.markValid(); return true; } else { this.markInvalid(this.reason); return false; } } return false; }, getVlmLeftPos: function() { if (Ext.isIE) return this.width; else return this.getEl().getOffsetsTo(this.getEl().parent())[0] + this.getEl().getWidth() + 2; }, markValid: function() { this.clearInvalid(); if (!this.validMarked){ this.validMarked = Ext.DomHelper.append(this.getEl().parent(), { cls:'x-form-valid-icon', style: 'left:' + this.getVlmLeftPos() }, true) } }, unMarkValid: function() { if (this.validMarked) { this.validMarked.remove(); delete this.validMarked; } }, markInvalid: function(reason) { this.unMarkValid(); markInvalid.call(this, reason); }, showLoadingMask: function() { this.requestExecuting = true; this.clearInvalid(); this.unMarkValid(); if (!this.validLoadMask){ this.validLoadMask = Ext.DomHelper.append(this.getEl().parent(), { cls:'x-form-loading-icon', style: 'left:' + this.getVlmLeftPos() }, true) } }, hideLoadingMask: function() { this.requestExecuting = false; if (this.validLoadMask) { this.validLoadMask.remove(); delete this.validLoadMask; } }, // private - remote validation request validateRemote:function() { this.rvOptions.params = this.rvOptions.params || {}; this.rvOptions.params.field = this.name; this.rvOptions.params.value = this.getValue(); this.showLoadingMask(); this.remoteValid = false; Ext.Ajax.request(this.rvOptions); }, // private - remote validation request success handler rvSuccess:function(response, options) { this.hideLoadingMask(); var o; try { o = Ext.decode(response.responseText); } catch(e) { throw this.cannotDecodeText; return false } if('object' !== typeof o) { throw this.notObjectText; return false } if(true !== o.success) { throw this.serverErrorText + ': ' + o.error; return false } var names = this.rvOptions.paramNames; this.remoteValid = true === o[names.valid]; this.reason = o[names.reason]; this.validate(); }, // private - remote validation request failure handler rvFailure:function(response, options) { this.hideLoadingMask(); throw this.requestFailText return false }, // private - runs from keyup event handler filterRemoteValidation:function(e) { if(!e.isNavKeyPress()) { this.requestExecuting = true; this.remoteValidationTask.delay(this.remoteValidationDelay); } }, // private - runs from field value changed event handler forceRemoteValidation:function(e) { this.remoteValidationTask.delay(0); } }); // remote validation defaults Ext.applyIf(field, { remoteValidationDelay:500, reason:'Server has not yet validated the value', cannotDecodeText:'Cannot decode json object', notObjectText:'Server response is not an object', serverErrorText:'Server error', requestFailText:'Server request failed' }); // install event handlers on field render field.on({ render:{single:true, scope:field, fn:function() { this.remoteValidationTask = new Ext.util.DelayedTask(this.validateRemote, this); this.el.on({ 'keyup': this.filterRemoteValidation, 'change': this.forceRemoteValidation, scope: this }) }} }); // setup remote validation request options field.rvOptions = field.rvOptions || {}; Ext.applyIf(field.rvOptions, { method:'post', scope: field, success: field.rvSuccess, failure: field.rvFailure, paramNames: { valid:'valid' ,reason:'reason' } }); } };
Code:.x-form-loading-icon { visibility:visible; display:block; width:16px; height:18px; background:transparent url(../images/design/loading.gif) no-repeat scroll 0pt 2px; position:absolute; top:0px; } .x-form-valid-icon { visibility:visible; display:block; width:16px; height:18px; background:transparent url(../images/design/valid.gif) no-repeat scroll 0pt 2px; position:absolute; top:0px; }
Last edited by Tasm; 28 Nov 2007 at 5:04 PM. Reason: Some corrections
Hi Saki!
Very nice plugin and very nice code!
Thanks for sharing!
I know from your various postings that you are a witty guy,
so let me share some thoughts about your plugin.
I took a deep look at it and think the performance can be
a little bit improved.
You did make the plugin a Singleton and put its configuration
on the field-level.
So the config is on a level which you have no control over
and you introduce new properties (rvOptions) to the
plugins container (field). While in most of the cases
this will make no problems, by murphy
Thanks for ideas. I'll consider all of 'em in next version.
Cheers,
saki
Jozef Sakalos, aka Saki
Education, extensions and services for developers at new http://extjs.eu
News: Grid MultiSearch Plugin, Grid MultiSort Plugin, Configuring ViewModel Hierarchy
Good to see your still doing your own stuff now you're in the developer team
Simple but great and effective plugin! I like the way you handle json parsing errors.
is possible assign to the remote plugin the form's baseparams?? i was looking for this, but i cann't make work![]()
You can put anything you want to rvOptions.params, e.g.:
PHP Code:
var field = new Ext.form.TextField({
plugins: [Ext.ux.plugins.RemoteValidator]
,rvOptions:{
params:{par1:'val1', par2:'val2', ...}
}
});
Jozef Sakalos, aka Saki
Education, extensions and services for developers at new http://extjs.eu
News: Grid MultiSearch Plugin, Grid MultiSort Plugin, Configuring ViewModel Hierarchy
Saki
First of all I want to thank you for this very nice piece of code.
Being a JavaScript newbie, all the things I did up until now didn't even come close to your code.
It's the echo.php which caught my eye. I couldn't understand why you would have it echo the $_POST-ed data ... where would it be sent to? To the client???
So I dug into it and tried to understand how it worked exactly.
PHP being more or less my piece of cake and being very strict on server side validation I modified the echo.php as follows:
So first of all: I do not believe that any piece of data that should be used later on the server (or stored in a database or whatever), could ever go without server side validation. Client side validation is very good to stop normal users from typing in something invalid but doesn't stand a chance against 'the bad guys out there'.PHP Code:
<?
sleep(1);
$o = new stdClass;
$o->success = true;
$o->valid = true;
// On Submit we should re-validate ALL fields!
foreach($_POST as $field=>$value) {
switch ("$field") {
case 'novalidation':
// No validation??? Duh!
break;
case 'clientvalidation':
// No validation??? Duh!
break;
case 'servervalidation':
if("ExtJS" <> $value) {
$o->valid = false;
$o->reason = "Validation of '$field' failed";
}
break;
case 'clientservervalidation':
if("ExtsJS" <> $value) {
$o->valid = false;
$o->reason = "Validation of '$field' failed";
}
break;
default:
// Is someone tampering or did we forget a field?
$o->valid = false;
$o->reason = "Unknown field: ".$field;
}
}
if ($o->valid) {
// We can now use the validated data on the server
$o->reason = "All's well!";
}
header("Content-Type: application/json");
echo json_encode($o);
?>
Secondly, even if the fields have been validated before Submit, they should absolutely be re-validated after Submit because no one can say that the $_POST (or $_GET) came from this form they're using!
Because we now have something to say to our users, we may want to show the success/failure reason from the success function of the submit:
One last thing and again, it's not a criticism, it's meant to be constructive: could it be that thePHP Code:
...
,buttons:[{
text: 'Submit'
,formBind:true
,handler:function() {
form.getForm().submit({url:'echo.php', method:'post', success:function(form, action){Ext.MessageBox.alert('Info', action.result.reason);}})
}
}]
...
just after the QuickTips is also some stray leftover code?PHP Code:
var submit = function() {
form.getForm().submit({url:'echo.php', method:'post'});
}
Anyway, it works fine without it ;-) and I thank you a lot because I'll be using your code in the application I'm writing for the Flemish Red Cross here.
Thanks!
Patrick