View Full Version : [New] Remote Field Validation Plugin
jsakalos
11-25-2007, 12:14 PM
Hi all,
I've just posted Remote Field Validation Plugin for Form Fields (http://extjs.com/learn/Plugin:RemoteValidator).
You can see demo here: http://aariadne.com/rvalidate
Enjoy!
TommyMaintz
11-27-2007, 08:27 PM
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)
var submit = function() {
form.getForm().submit({url:'echo.php', method:'post'});
}
jsakalos
11-28-2007, 04:15 AM
Yes, you're right. It's some stray code. I'll remove it.
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:
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'
}
});
}
};
and css:
.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;
}
tidal
11-29-2007, 07:52 AM
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
jsakalos
11-29-2007, 11:35 AM
Thanks for ideas. I'll consider all of 'em in next version.
Cheers,
saki
JorisA
12-04-2007, 08:16 PM
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.
evilized
12-05-2007, 08:31 AM
is possible assign to the remote plugin the form's baseparams?? i was looking for this, but i cann't make work :(
jsakalos
12-05-2007, 03:25 PM
You can put anything you want to rvOptions.params, e.g.:
var field = new Ext.form.TextField({
plugins: [Ext.ux.plugins.RemoteValidator]
,rvOptions:{
params:{par1:'val1', par2:'val2', ...}
}
});
pludikhu
12-05-2007, 03:58 PM
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:
<?
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);
?>
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'.
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:
...
,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);}})
}
}]
...
One last thing and again, it's not a criticism, it's meant to be constructive: could it be that the
var submit = function() {
form.getForm().submit({url:'echo.php', method:'post'});
}
just after the QuickTips is also some stray leftover code?
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
jsakalos
12-06-2007, 05:06 AM
Hi Patrick,
my answers follow:
Saki
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???
echo.php is there purely for the demonstration purposes and/or debug. You post your form and you get back data that was really posted. Nothing else.
And yes, data is send back to client.
So I dug into it and tried to understand how it worked exactly.
There are two server side scripts: echo.php and validate.php both of them being demo-only. validate.php handles validation requests sent after each keystroke (after some delay) and echo.php handles form submit.
PHP being more or less my piece of cake and being very strict on server side validation I modified the echo.php as follows:
Yes, this is one of possible server side validations however it ceases to be "echo" script anymore and it becomes "validate" script.
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'.
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!
Well, both client validation and server validation have their purposes. The degree and form and if to use one or both depends on nature of application. What's good is that we have tool to implement them easily.
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:
...
,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);}})
}
}]
...
Yes, one of the possible ways of announcing an invalid input is to show a message box. Of course, this is not the only way and in some cases is undesirable. For example, I use remote validation to check if the value entered is unique by searching a database table server side. Validation is triggered by keyup event (after some delay). Showing a message box after a couple of keystrokes would be very irritating in this case. Therefore, I just mark the form field invalid with reason shown in QuickTip.
One last thing and again, it's not a criticism, it's meant to be constructive: could it be that the
var submit = function() {
form.getForm().submit({url:'echo.php', method:'post'});
}
just after the QuickTips is also some stray leftover code?
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!
PatrickYes, it's stray code. It's not in the tutorial anymore but could be left in the downloaded code.
weazle
12-12-2007, 09:07 AM
Hi Saki,
since this is my first post in the forums, first of all: ExtJS is great, thanks to all people who spent their time making it become what it is now.
I've been playing around with the RemoteValidation extension, works like a charm. The only thing I've come across is, when I have preset values in the Fields (i.e. fields have a value at the time the form is rendered), remote validation is not done as I would have expected.
Example field configuration:
{
"allowBlank": false,
"plugins": [Ext.ux.plugins.RemoteValidator],
"rvOptions": {"url": "actions/validate.jsp"},
"name": 22,
"xtype": "field",
"value": 1.2,
"fieldLabel": "Fuel"
}
In the rendered HTML-Form, each field with a preset value is marked invalid, telling me that server validation has not been performed yet. What I would expect is that validation of preset fields is already done when the form is rendered. So I changed the "render part" of your plugin a little bit:
// 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, this);
// START NEW CODE -- validate preset values
if (field.getValue()) {
this.remoteValidationTask.delay(this.remoteValidationDelay);
}
// END
}}
});
This solves my problem. But since I'm pretty new to the whole library, I wonder if it is "the" way to do it. I also wanted to share this in case other people having the same problem. What do you think about it?
Regards,
Benjamin
jsakalos
12-12-2007, 11:19 AM
If you're absolutely sure that fields with preset values are valid you can set remoteValid flag to true to save server round trips.
weazle
12-14-2007, 07:21 AM
If you're absolutely sure that fields with preset values are valid you can set remoteValid flag to true to save server round trips.
Works perfect for me, thank you!
christocracy
12-14-2007, 03:48 PM
Great plugin, mr JSakalos. just what I needed.
2 things.
I didn't see a way to prevent server-validation firing until client-validation passed. I added this:
(eg: I use this on an airport-code field -- I don't want validation firing until minLength: 3 is satisfied)
// private - remote validation request
validateRemote:function() {
if (!validate.call(this)) { return false; } // <-- why server-validate if client-validation isn't valid??
2. I attached the plugin to ComboBox, therefore I need to validate on "rawValue".
// private - remote validation request
,validateRemote:function() {
if (!validate.call(this)) { return false; } // <-- why server-validate if client-validation isn't valid??
this.rvOptions.params = this.rvOptions.params || {};
this.rvOptions.params.field = this.name;
#####################################
# changed this line to check for ComboBox
this.rvOptions.params.value = (!this instanceof Ext.form.ComboBox) ? this.getValue() : this.getRawValue();
Ext.Ajax.request(this.rvOptions);
}
jsakalos
12-15-2007, 05:19 AM
Great! You're free to modify or improve this plugin for you needs... ;)
I just wouldn't wait with server validation until 3 letters as 2 letter code can be invalid...
christocracy
12-16-2007, 04:22 PM
*** bug ***
Ext.ux.plugins.RemoteValidator::isValid
Problem:
when field is disabled, isValid will still validate upon the state of "remoteValid"
Solution:
// private
,isValid:function(preventMark) {
if (this.disabled) { return true; } // <--- fix: when field is disabled, return true immediately.
return isValid.call(this, preventMark) && this.remoteValid;
}
jsakalos
12-17-2007, 03:29 AM
Yes, you're right. Thank's for debugging.
attiato
01-18-2008, 07:39 AM
Hi everybody,
i have some trouble with using remoteValidation plugin.
It seems like the field value sent, is always the same, even if i type different text in the field.
What could be the problem?
I check with firebug.
Example: first time i type "tr",
firebug post is: value: tr,
then i continue typing "try",
firebug post is: value: tr,
and so on...
What could be the problem?
I don't think the problem is the plugin, but i post this here, because maybe someone else had this problem and knows how to solve it.
my input looks like this:
var textfield = new Ext.form.TextField({
allowBlank:false,
name:"somename",
fieldLabel:'Insert name',
plugins:[Ext.ux.plugins.RemoteValidator],
rvOptions: {
url:'t/validate.php'
}
});
By the way, my form is in an Ext.Window. Could this be the problem?
christocracy
01-18-2008, 10:38 AM
I posted your code into one of my forms (which happens to exist upon a Window) and it works for me.
anjelika
02-19-2008, 11:00 AM
Hello,
Nice addon!
I have a (noob) question.
How do I interpret the response from AJAX?
e.g my app returns {success: true, valid: false, reason:'undefined error'}
How can I process the response in my success(response, options){} function (or should I process it some place else?)?
I know that using "response.responseText" it shows the whole message ({success: true, valid: false, reason:'undefined error'}), all I want to do is to break the values apart (e.g. test the validation).
Thanks
jsakalos
02-19-2008, 11:06 AM
You do not need to do anything because that text is displayed same way as any other invalid text (tooltip, side icon or bellow the field).
anjelika
02-19-2008, 01:12 PM
Hello,
Thanks for the prompt reply.
I got the ideea behing this plugin but here's what I need to do:
1. enter an ID in an input box.
2. the id is searched in background (using ajax provided by your plugin) to match a record in a database (php server side).
3. if a record is found I need to return the data associated with that record that is loaded into a form (the one containing the ID field also).
Now, here is how I am thinking to do that (I am open to suggestions):-?
1. when the ID field is modified the request is triggered and performs the background check to the database.
2. if the ID is found, I return the {success: true, valid: true} response.
Can I return the collected data into this response also? That will save me some steps (e.g. {success: true, valid: true, results:[{name: xxx, address:yyy, phone: zzz}] ???
3. If I can't return the collected data into the previous request together with the ajax response I have to populate the form fields (by using for.load('url...')), that's why I need to process the response from your plugin by myself.
Tho, I am not sure how to do that..here;s some sample code:
var id = new Ext.texfield{[
....
....
plugin: [RemoteValidation...]
rvOptions: { url:'validate.php', success:function(response, options){ if (response.valid == true) form.load('url')}
The underline function is my unsolved problem :-?
Is there another better place to process the response and proceed accordingly that the success function?
Thanks for your time ;)
jsakalos
02-19-2008, 01:45 PM
Well, this is validationplugin and it's basic purpose is field validation. You could put your callback function to rvOptions and you could implement the functionality you describe in that callback but it seem quite awkward and overcomplicated to me.
The straightforward solution would be to listen to field's keyup event (or an another one), send request and process result. If you need this functionality in more than one form, create an extended class for it.
pludikhu
03-03-2008, 10:32 AM
Saki
You said it was OK to add some functions, right?! Here's one I wanted to share, might not mean a lot to you pro's but perhaps for some newbies like me ...
My requirement was e.g. filling in several e-mail addresses in one field and having that checked by the server. But with the 500 milliseconds delay, one could hardly type anything in the field without the server validation firing (whenever a slow user hesitated or so).
So I set the delay to a higher value but then wanted to have the remote validation fire immediately on blur.
Therefore I changed the event handling as follows:
// 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, this);
}},
blur:{single:false, scope:field, fn:function() {
this.validateRemote();
this.remoteValidationTask.cancel();
}}
});
The last line (this.remoteValidationTask.cancel(); ) for those who don't know why: is to cancel the delayed keyup event.
Good checking to all ;-)
Patrick
jsakalos
03-03-2008, 12:20 PM
Looks good!
Have you thoroughly tested it if it doesn't break anything? If yes I'd add it to the main stream - I like the idea.
pludikhu
03-03-2008, 03:05 PM
I did indeed test it, Saki.
It looks OK in my test configuration. Firebug doesn't complain.
But then again, I'm a total noob in JS programming so I'm afraid you cannot take my word for it, sorry.
But it looks pretty straightforward doesn't it?!
Patrick
jsakalos
03-03-2008, 03:16 PM
Yeah, just you don't need single:false - it's default but that's just cosmetics.
omegafox
03-27-2008, 07:12 PM
is it possible to use this plugin for cross validations with two date fields and numberfields?
jsakalos
03-27-2008, 09:51 PM
You would need to patch it somehow as the design concept is per-field validation. In another words, only the field name/value is posted to the server for validation.
sanjshah
03-28-2008, 08:28 AM
nice plug-in and looks very useful, could some please show an ASP example of a simple validation?
Thanks!
jsakalos
03-28-2008, 08:38 AM
Unfortunately not, because I do not use Micro$oft "products".
chiru
04-01-2008, 03:15 AM
Hi!!
I'm trying to validate some parameters in the server side, and your plugin looks really good!!!
But can you share a simple example with a servlet???
Thanks in advance!!!!
jsakalos
04-01-2008, 08:34 AM
Server side varies very much; some use php, some jsp, some asp, etc... So it is up to you to code server side logic.
omegafox
04-03-2008, 11:55 AM
I am having hard time to set value in RemoteValidator's params with valHourTime and valMinTime and I always get empty values. after POST.
I tried to use with var valHourTime = Ext.getCmp('hourtime');
AND
var valHour = simple.getForm().findField('hourtime').getValue();
They all gave me blank values.
This is my POST result:
field: minutesUsed
hours:
value:12 //number of minutes
Can you tell me what did I wrong do with it? Please
{
{
xtype:'numberfield',
allowNegative: false,
fieldLabel: 'Minute Used',
name: 'minutesUsed',
width: 95,
minValue: 1,
id:'minutetime',
allowBlank:false,
plugins:[Ext.ux.plugins.RemoteValidator]
,rvOptions: {
url:'validate.php', params:{hours: valHourTime}} //problem: wont get any value from hoursUsed field
}
},{
xtype:'numberfield',
allowNegative: false,
fieldLabel: 'Hour Used',
name: 'hoursUsed',
width: 95,
minValue: 1,
id:'hourtime',
allowBlank:false,
plugins:[Ext.ux.plugins.RemoteValidator]
,rvOptions: {
url:'validate.php', params:{minutes: valMinTime}}//problem: wont get any value from minutesUsed field
}
jsakalos
04-03-2008, 12:04 PM
This looks like the problem is outside of the validator. Easiest is to give field ids and then Ext.getCmp('that-id').getValue()
omegafox
04-03-2008, 02:33 PM
Thank you for reply so quickly. You are right about that but still I couldnt figure it out what did I set it wrong. Let's check if I am doing right or not. About field ids, I already set it up as id:'minutetime' id:'hourtime' (see my previous post ) and did set var valHourTime = Ext.getCmp('hourtime') outside the formpanel. Is that all? Am I missing anything?
jsakalos
04-03-2008, 04:02 PM
Well, I cannot say before seeing the code but this is not good place for general queries that are not RemoteValidator specific. Open new thread in Help forum instead.
shrus
05-02-2008, 07:28 AM
Hello,
Nice plugin!
But I have some problem with it.
I have a edit action in grid. And form is loaded (calls for ex. editFrom.form.load()). So data is loaded but shows message "Server has not yet validated the value". But server validation has not called.
Does any body know how to fix it?
Thanks, Ruslan
P.S. Sorry for my English, I'm ukrainian.
jsakalos
05-03-2008, 06:38 AM
If you load values from server you are sure are valid you can pass config option remoteValid:true.
DaNCeT
05-10-2008, 06:03 AM
Quick suggestion, replace:
// 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, this);
}}
});
With:
// 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(this.validationEvent, this.filterRemoteValidation, this);
}}
});
If you don't, the remote validation will not always be triggered during the validationEvent set for your field.
jsakalos
05-10-2008, 06:46 AM
Yes, you're right; this way validator honors validation event set on field. Updating source.
DaNCeT
05-11-2008, 07:05 AM
I'm having more issues with the remote validation atm, regarding validation of Combo (with source from transformed select) and with validating a datefield. Will keep you updated.
DaNCeT
05-11-2008, 08:25 AM
I can't seem to enable the remote validation for a datefield or a combobox (not from a transformed, select, nor with a local store as config option).
Any suggestions?
jsakalos
05-11-2008, 09:12 AM
Difficult to say... I validate combos and dates w/o problems...
Is the request sent to server? What comes back?
DaNCeT
05-11-2008, 02:52 PM
For some reason it's not sending a validation request to the server...
I have tried various things, just to make sure it was not an interference with any other code, I took your example form and added this item:
{
fieldLabel:'Validate combo',
xtype:"combo",
id:"combovalidation",
name:"combovalidation",
mode:"local",
triggerAction:"all",
forceSelection:true,
enableKeyEvents:true,
allowBlank:false,
store: [[1, 'value 1'],[2, 'value 2'],[3, 'value 3'],['ExtJS', 'value ExtJS']],
plugins : [Ext.ux.plugins.RemoteValidator],
rvOptions : {
url:'validate.php'
}
}
The server is only sending a validation request when I type in the field (as it's triggering the keyup event).
However when selecting a value, it's not validating.
I have tried adding:
validationEvent:'change',
This never triggers the validation.
And when trying this:
validationEvent:'select',
It triggers the validation only when clicking the triggerfield.
As i need a combobox that mimics a native select (so I disable typing, and only allow the usage of the trigger field), it won't work.
The same with the datefield, it never triggers the validation, my best guess is that it's a related problem...
DaNCeT
05-11-2008, 04:08 PM
After digging a bit deeper I found out that the remote validation is being triggered like this:
this.el.on('keyup', this.filterRemoteValidation, this);
However, adding this during config of the combobox does trigger the validation:
listeners: {
'select': function(combo, record, index) {
combo.remoteValidationTask.delay(0);
}
}
So the change I proposed yesterday is of no use, as the remote validation is being bound to this.el, instead of just this...
jsakalos
05-11-2008, 07:58 PM
Remote validation of combo on select does not make any sense as if some of the values in the list is invalid why it is there in the first place.
It does make sense for user typed values in combo and in that case keyup triggers remote validation.
DaNCeT
05-12-2008, 02:26 AM
Remote validation of combo on select does not make any sense as if some of the values in the list is invalid why it is there in the first place.
It does make sense for user typed values in combo and in that case keyup triggers remote validation.
It does make sense if you want to build a secure form (hence the reason I chose for remote validation). The project I'm working at requires a very high level of security, and by validating the fields remotely I keep all field requirements away from 'those eyes'.
Yes, I populate my como with values/text loaded at init, but since the source can easily be tampered with I validate ALL fields remotely, so also the combo boxes. This way I can assure the form is completely valid at submission...
jsakalos
05-12-2008, 05:26 AM
Well, then you need to hack it somehow, to add another events that trigger validation.
malord
05-13-2008, 05:38 PM
I really like this plugin and am very glad there are people developing things like this for ExtJS. Unfortunatley though, when I was trying to get it working in my app I noticed that the validateRemote() function was only being called on the 'keyup' (or validationEvent) event, and I need the validation called onBlur as well. I was also getting a lot of 'Server has not yet validated the value' errors, so this solution should take care of both of those issues.
In the native ExtJS code, it automatically calls validate() whenever it needs to validate (onBlur or keyup), so I am proposing that we re-order the validation functions in this plugin. More specifically, we can change validate() to something like validateThis() and change validateRemote() to validate() and have the rvSuccess() function call validateThis(). This will also eliminate the need for overriding the event handlers since they are handled by ExtJS automatically. Here is the code for the updated plugin (with some other minor modifications included from this thread):
[code]/**
* Ext.ux.plugins
*
* @author Ing. Jozef Sak
malord
05-14-2008, 03:00 PM
Damn I thought I had a good solution, but the code above does not allow the form to submit since the submit function calls the validate function which does not return the validate value but updates it asynchronously. I added a return this.validateThis(); to the end of the validate() function to fix this, but then this allows you to change the field and if you are quick enough submit the form before it validates remotely. Seems like I need to be able to perform the remote validation synchronously instead of asynchronously, but I'll keep working on it to see if I can find a good solution.
malord
05-15-2008, 05:20 PM
Yay, I finally got this plugin to work the way I wanted it to. You really do need the listener on the validationEvent in order to prevent the form from being submitted right after you input something. I disabled validateOnBlur because it does not call the remote validation. If you do call the remoteValidation on blur you won't be able to submit the form if you are currently focused on the field. It is not necessary anyways because the field is validated on the validationEvent.
I also added support for throwing in an extra field when calling the ajax for validation. Just add "extrafield: fieldname" to the rvOptions array. You can access the field name on the server as 'extrafield' and the field value as 'extrafieldvalue'. This can be used to validate matching passwords or if you want to have unique values for a field (you need to pass the ID of the record in order to tell if the input is for the current record or a different record).
[CODE]// vim: ts=4:sw=4:nu:fdc=4:nospell
/**
* Ext.ux.plugins
*
* @author Ing. Jozef Sak
LeandroC
05-26-2008, 06:13 PM
I have a problem catching the values of POST data with ASP in the rvalidate, but It works fine with submit or an ajax request.
Any known issues with that?
Here is part of my code.
[code] items: [{
xtype:'numberfield',
fieldLabel: 'N
jsakalos
05-27-2008, 06:46 AM
I call standard Ajax.request for field validation so this should not be an issue. As to asp, I know nothing about it - I don't use M$ "products". Somebody else?
MichaelOstrovsky
06-07-2008, 01:00 PM
thanks for the great plug in . i have only one problem with it - when i load data to my form ( for editing ) , the filed render invalid with "server has not yet validated the value". please help me disable this behavior..
jsakalos
06-08-2008, 08:55 AM
There is one config option for that: remoteValid:true - when you are sure that form loads valid.
yanick
06-17-2008, 09:09 AM
This post is offtopic, sorry :">
But, on this URL
http://aariadne.com/Theseus_celofiremn%FD_adres%E1r.html
You have gramatical error(i->y)
"-plnia sa va
jsakalos
06-18-2008, 07:14 AM
Yeah, was done by a lame designer... The site has not been updated for a long time, portfolio changed so it needs a complete revamp. Anyway, thank you.
PS: Contact me on Skype if you're from Slovakia, I'm looking for coders.
battisti
06-18-2008, 05:18 PM
I try RV plugin and it's very usefull.
One question.
In some cases i would like to make the validation only when the user click in submit button and not every field blur. it's possible ?
[]'s Anselmo Battisti
jsakalos
06-18-2008, 07:35 PM
You'd need to hack the code then...
battisti
06-19-2008, 07:27 AM
thx i will do it
battisti
06-19-2008, 10:33 AM
Looking in the api documentation i see if what i whant is very simple to do, not need a plugin
api url
http://extjs.com/deploy/dev/docs/?class=Ext.form.Action.Submithttp://extjs.com/deploy/dev/docs/?class=Ext.form.Action.Submit (http://extjs.com/deploy/dev/docs/?class=Ext.form.Action.Submit)
var form = new Ext.FormPanel({
id : 'company-form',
frame : false,
labelAlign : 'left',
bodyStyle : 'padding:5px',
method : 'POST',
url: url+'update',
layout : 'column', // Specifies that the items will now be arranged in
// columns
items : [{
xtype : 'fieldset',
labelWidth : 90,
title : 'Company details',
defaults : {
width : 140
}, // Default config options for child items
defaultType : 'textfield',
autoHeight : true,
bodyStyle : Ext.isIE
? 'padding:0 0 5px 15px;'
: 'padding:10px 15px;',
border : true,
style : {
"margin-left" : "10px", // when you add custom margin in IE 6...
"margin-right" : Ext.isIE6
? (Ext.isStrict ? "-10px" : "-13px")
: "0"
},
items : [{
fieldLabel : 'id',
name : 'industryId',
allowBlank: false
}, {
fieldLabel : 'Nome',
name : 'industryName',
allowBlank: false
}],
buttons : [{
text : 'Salvar',
handler: function(){
Ext.getCmp('company-form').form.submit();
}
}, {
text : 'Cancelar'
}]
}]
});
And json return
{"success":false,"errors":{"industryName":"O tamanho do nome deve ter menos do que 10 caracteres"}}
but the plugin is great :)
illuminum
07-08-2008, 10:45 PM
how come you (apparently) don't need to instantiate the plugin with the new keyword? I'm about to try this plugin out, this just seemed weird to me.
jsakalos
07-09-2008, 02:00 AM
The plugin is not class, it is singleton object therefore now new keyword is required/allowed.
illuminum
07-09-2008, 07:33 AM
Makes sense. A new pattern to add to my utility-belt--thanks.
LeandroC
08-04-2008, 03:32 PM
I have a trigger field to validate, but when becomes valid the x-form-valid-icon appears over the trigger image, the invalid icon works ok.
Could be there something in the css that can't be displayed at the right side of the trigger field?
Thanks
jsakalos
08-04-2008, 04:47 PM
Any picture and/or code?
LeandroC
08-04-2008, 10:46 PM
Here it is a portion of the code. both fields has rvalidate, Screens can show how the icons are displayed. The css definition of .x-form-valid-icon it's the original.
[PHP]
items:[{
columnWidth:.5,
layout: 'form',
border:false,
frame: false,
items: [{
xtype:'textfield',
fieldLabel: 'N
jsakalos
08-05-2008, 04:17 AM
Where did you get x-form-valid-icon from? I've grepped Ext resources and I've found no reference to it. Also, rendering problems shouldn't be related to this plugin as it has no UI.
LeandroC
08-05-2008, 02:35 PM
Oh, sorry Saki, i had found that the valid icon was a modification of your work done by Tasm at post #4 http://extjs.com/forum/showthread.php?p=92693#post92693
.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;
}
Sorry for the mistake, I will ask him about it.
thephatp
08-30-2008, 09:14 PM
Hi Saki, this is a great plug-in and very useful!
I do have a question about comboboxes. I read in a previous post that you don't have any problems with it, but I can't seem to get it to post values correctly when a user types in the box.
For example, I'm testing to make sure the user selects a valid US state, but if they type in the box, who knows. Every time the validator is used, it comes back with an error, because incorrect values are posted.
I'm seeing problems in two cases:
(1) First action in box is User Typed
Firebug tells me the following on the Console Tab (then "Post" tab):
field=state&value=
Why would the value be empty? Where does it get this value from?
Now, if I select something from the box, it works just fine. In this case, I select "Alaska" from the dropdown box, and the Firebug tells me the following:
field=state&value=AK
So, all seems good. But this leads to my second problem:
(2) User types in box AFTER a selection has been made
After user types `asdf` in the box (after a selection was made and validated), Firebug gives this info:
field=state&value=AK
It posted the last value that was selected from the box, not the actual value that was typed. Thus, it returns true as if the data passed validation, but it should not.
Why would it not be updating the values and sending the correct data?
Below is my code:
new Ext.form.ComboBox({
fieldLabel: 'State'
, id:'id_combobox_state'
, hiddenName:'state'
, name:'state'
, store: new Ext.data.SimpleStore({
fields: ['abbr', 'state']
, data : Ext.comboboxdata.states // from stateList.js
})
, valueField:'abbr'
, displayField:'state'
, typeAhead: true
, mode: 'local'
, triggerAction: 'all'
, emptyText:'Select a state...'
, selectOnFocus:true
, allowBlank:false
, anchor:'95%'
, plugins:[Ext.ux.plugins.RemoteValidator]
, rvOptions: { url:'validateAccountFields.php' (http://extjs.com/forum/'validateAccountFields.php') }
}) // eof new ComboBox
Any ideas?
Thanks in advance for the help...and thanks for the plug-in!!
jsakalos
08-31-2008, 03:07 AM
It could be that getValue, that is used in validator, returns valueField but we when user types he types displayField value. Try to use getRawValue in the plugin for combo if it helps and let me know please.
thephatp
08-31-2008, 11:12 PM
It could be that getValue, that is used in validator, returns valueField but we when user types he types displayField value. Try to use getRawValue in the plugin for combo if it helps and let me know please.
I'm not sure why this didn't get posted earlier today, but I'll try again. Sorry if you get the same info twice.
Saki, if you are talking about the change recommended by `christocracy` on pg. 2 (I think), then yes, I've already tried that, and unfortunately, I got the exact same results as the information above. Just for a sanity check, I tried it again both with and without, but same results.
As an aside, it suffices for me in my current situation to set my combobox's parameter `editable` to false, so only the selection can occur, but this doesn't fix the problem, and I'm sure others will need a different solution.
If there is anything else that I can try, just let me know, and I'd be more than happy to report back.
Thanks,
Chad
Ender27182818
09-17-2008, 08:19 PM
This should be a pretty simple question for experienced extjs coders. I want to use the remote validator plugin to validate my form data on a textfield that, at times, is filled with information from the server. For instance, if a user clicks on a combo box entry, the field will be filled with a pre-set value. Whenever I do this, I get the message that the value hasn't been validated. Now, I know that I should be able to use remoteValid somehow to stop that message, I'm just not sure how. What I tried was this inside the event handler that fills the text field's value:
var my_address = record.data['Address'];
this.address.setValue(my_address);
Ext.apply(this.address, {remoteValid:true});
Here 'this' is the panel containing my combo box and my text field. The text field is this.address and record.data is the record selected by the combo box. Now, this code doesn't work. I've also tried the following in my text field code:
Pricing.CustomerAddressTF = Ext.extend(Ext.form.TextField, {
fieldLabel : 'Address'
,listeners : { change : {fn : change_address} }
,plugins : [Ext.ux.plugins.RemoteValidator]
,rvOptions : {
url : './db/change_address.php'
,remoteValid : true
}
,initComponent:function() {
Pricing.CustomerAddressTF.superclass.initComponent.apply(this, arguments);
}//end initComponent
}); //close the viewport
and
Pricing.CustomerAddressTF = Ext.extend(Ext.form.TextField, {
fieldLabel : 'Address'
,listeners : { change : {fn : change_address} }
,plugins : [Ext.ux.plugins.RemoteValidator]
,rvOptions : {
url : './db/change_address.php'
}
,remoteValid : true
,initComponent:function() {
Pricing.CustomerAddressTF.superclass.initComponent.apply(this, arguments);
}//end initComponent
}); //close the viewport
But that's because mostly I don't understand what was meant earlier in this forum when Saki said:
There is one config option for that: remoteValid:true - when you are sure that form loads valid.
I can't pass that in to a constructor, because the plugin is a singleton. So, where would I use that 'config option' if I'm using pre-configured classes?
Thanks,
-Eli Ribble
jsakalos
09-18-2008, 04:01 AM
Try this validator and let me know how it works please. It is a successor of RemoteValidator I use but it was not published yet.
// vim: ts=4:sw=4:nu:fdc=4:nospell
/**
* Ext.ux.form.ServerValidator
*
* @author Ing. Jozef Sakalos
* @copyright (c) 2008, by Ing. Jozef Sakalos
* @date 8. February 2008
* @version $Id: Ext.ux.form.ServerValidator.js 250 2008-05-10 18:36:44Z jozo $
*
* @license Ext.ux.form.ServerValidator is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/
/*global Ext, console */
/**
* @class Ext.ux.form.ServerValidator
* @extends Ext.util.Observable
* @constructor
*/
Ext.ux.form.ServerValidator = function(config) {
Ext.apply(this, config, {
url:'/request.php'
,method:'post'
,cmd:'validateField'
,paramNames:{
valid:'valid'
,reason:'reason'
}
,validationDelay:500
,logFailure:true
,logSuccess:true
});
Ext.ux.form.ServerValidator.superclass.constructor.apply(this, arguments);
}; // eo constructor
// extend
Ext.extend(Ext.ux.form.ServerValidator, Ext.util.Observable, {
// {{{
init:function(field) {
this.field = field;
// save original functions
var isValid = field.isValid;
var validate = field.validate;
Ext.apply(field, {
// is field validated by server flag
// serverValid: undefined !== this.serverValid ? this.serverValid : false
serverValid: true
// private
,isValid:function(preventMark) {
if(this.disabled) {
return true;
}
return isValid.call(this, preventMark) && this.serverValid;
}
// private
,validate:function() {
var clientValid = validate.call(this);
// return false if client validation failed
if(!this.disabled && !clientValid) {
return false;
}
// return true if both client valid and server valid
if(this.disabled || (clientValid && this.serverValid)) {
this.clearInvalid();
return true;
}
// mark invalid and return false if server invalid
if(!this.serverValid) {
this.markInvalid(this.reason);
return false;
}
return false;
} // eo function validate
}); // eo apply
// install listeners
this.field.on({
render:{single:true, scope:this, fn:function() {
this.serverValidationTask = new Ext.util.DelayedTask(this.serverValidate, this);
this.field.el.on(this.validationEvent, function(e){
this.field.serverValid = false;
this.filterServerValidation(e);
}, this);
// this.field.el.on({
// keyup:{scope:this, fn:function(e) {
// this.field.serverValid = false;
// this.filterServerValidation(e);
// }}
//// ,blur:{scope:this, fn:function(e) {
//// this.field.serverValid = false;
//// this.filterServerValidation(e);
//// }}
// });
}}
});
} // eo function init
// }}}
,serverValidate:function() {
var options = {
url:this.url + '?#' + (this.field.name || this.name)
,method:this.method
,scope:this
,success:this.handleSuccess
,failure:this.handleFailure
,params:this.params || {}
};
Ext.applyIf(options.params, {
cmd:this.cmd
,field:this.field.name || this.name
,value:this.field.getValue()
,table:this.table
});
Ext.Ajax.request(options);
} // eo function serverValidate
// {{{
,filterServerValidation:function(e) {
if(this.field.value === this.field.getValue()) {
this.serverValidationTask.cancel();
this.field.serverValid = true;
return;
}
if(!e.isNavKeyPress()) {
this.serverValidationTask.delay(this.validationDelay);
}
} // eo function filterServerValidation
// }}}
// {{{
,handleSuccess:function(response, options) {
var o;
try {o = Ext.decode(response.responseText);}
catch(e) {
if(this.logFailure) {
this.log(response.responseText);
}
}
if(true !== o.success) {
if(this.logFailure) {
this.log(response.responseText);
}
}
this.field.serverValid = true === o[this.paramNames.valid];
this.field.reason = o[this.paramNames.reason];
this.field.validate();
} // eo function handleSuccess
// }}}
// {{{
,handleFailure:function(response, options) {
if(this.logFailure) {
this.log(response.responseText);
}
} // eo function handleFailure
// }}}
// {{{
,log:function(msg) {
if(console && console.log) {
console.log(msg);
}
} // eo function log
// }}}
});
// shortcut
Ext.ux.ServerValidator = Ext.ux.form.ServerValidator;
// register xtype
Ext.reg('servervalidator', Ext.ux.form.ServerValidator);
// eof
hAmpzter
09-20-2008, 06:56 PM
Thank you Saki for another great addon! :)
Found an error though!
Start line 95, original:
this.field.serverValid = false;
this.filterServerValidation(e);
}, {scope: this});
Fix:
this.field.serverValid = false;
this.filterServerValidation(e);
}, this);
Question: Is the 'blur'-event the best to set on validationEvent for an textfield?
jsakalos
09-20-2008, 06:58 PM
I have it keyup.
hAmpzter
09-22-2008, 03:34 AM
Ahhh, that would maybe work better! :) Thx!
Try this validator and let me know how it works please. It is a successor of RemoteValidator I use but it was not published yet.
I was using the original Ext.ux.plugins.RemoteValidator and have found a problem during testing after updating Ext to 2.2 (not sure if it's related or not). I decided to give the new validator a shot, but am getting the following error when initializing: "p.init is not a function". Is the method of using Ext.ux.form.ServerValidator different than Ext.ux.plugins.RemoteValidator? If so, do you have a small example of how it can be used?
Thanks,
Tim
jsakalos
09-22-2008, 03:21 PM
There was one bug pointed out a couple of posts back. Take the code now it's been fixed.
hAmpzter
09-23-2008, 04:33 AM
The new ServerValidator isn't an Singleton as the first one... So you have to use:
plugins:[new Ext.us.form.ServerValidator({ ... config ... })]
damsfx
09-25-2008, 12:51 PM
"Ext.ux.form is undefined" when using the successor of RemoteValidator.
:-?
jsakalos
09-25-2008, 03:05 PM
Add Ext.ns('Ext.ux.form'); at the beginning of the code.
damsfx
09-26-2008, 04:12 AM
Thank's a lot Jozef ... yesterday I was too tired to do anything !
I-|
The only think that I can't do is to use the "Get" method ... adding (#fieldname) in url break the querystring.
lencho
10-09-2008, 11:00 PM
the firebug show the error:uncaught exception: Server error: undefined
why??
my server return the JSON object is [{"success":false},{"errors":"this is bad value "}] or [{"success":true}]
please help me,thanks
jsakalos
10-13-2008, 03:55 AM
{"success":false, "errors":"this is bad value"}
mgallinucci
02-27-2009, 04:09 AM
Hi Saki,
in my application I need to validate a field, considering other fields value, so I can't set all params when I'm creating the object. I need to specify params as functions and evaluate the function every time I validate the field; so I modified validateRemote:
validateRemote:function() {
this.rvOptions.params = this.rvOptions.params || {};
this.rvOptions.params.field = this.name;
this.rvOptions.params.value = this.getValue();
var actualOptions = {params:{}};
for (propName in this.rvOptions.params){
var p = this.rvOptions.params[propName];
if (typeof p === 'function')
actualOptions.params[propName] = p.call(this);
else
actualOptions.params[propName] = p;
}
Ext.applyIf(actualOptions,this.rvOptions);
Ext.Ajax.request(actualOptions);
}
And now I can use the plugin in this way:
{
id: 'titolo',
name: 'titolo',
xtype: 'textfield',
fieldLabel: 'Titolo',
plugins:[Ext.ux.plugins.RemoteValidator],
rvOptions: {
url: URL.isTitoloUnivoco,
params:{
idCategoria: function(){return Ext.getCmp('myForm').getForm().findField('idCategoria').getValue()}
}
}
}
If you want, you can use my code in plugin.
jsakalos
02-27-2009, 05:12 AM
Thanks for sharing. Maybe it helps others with a similar problem.
pludikhu
03-05-2009, 04:49 PM
Saki
I tried your new serverValidate.
It seems to run only once on a certain field unless you click outside the field an go back into it. (B.t.w. I'm using it together with InlineTextField user extension.)
Would that be my error?
...
plugins:[new Ext.ux.form.ServerValidator({
validationEvent:'keyup',
validationDelay: delay,
url: rvUrl,
method: 'POST',
success: function(result, request) {
this.handleSuccess(result, request);
var json = Ext.util.JSON.decode(result.responseText);
if (json.reason) Ext.MessageBox.alert('Info', json.reason);
},
failure: failureFn
})],
...
Thx for any help!
Patrick
jsakalos
03-05-2009, 04:58 PM
No idea. I have no clue what is that other extension.
attiato
03-08-2009, 08:21 AM
Hi Saki,
in my application I need to validate a field, considering other fields value, so I can't set all params when I'm creating the object. I need to specify params as functions and evaluate the function every time I validate the field; so I modified validateRemote:
validateRemote:function() {
this.rvOptions.params = this.rvOptions.params || {};
this.rvOptions.params.field = this.name;
this.rvOptions.params.value = this.getValue();
var actualOptions = {params:{}};
for (propName in this.rvOptions.params){
var p = this.rvOptions.params[propName];
if (typeof p === 'function')
actualOptions.params[propName] = p.call(this);
else
actualOptions.params[propName] = p;
}
Ext.applyIf(actualOptions,this.rvOptions);
Ext.Ajax.request(actualOptions);
}
And now I can use the plugin in this way:
{
id: 'titolo',
name: 'titolo',
xtype: 'textfield',
fieldLabel: 'Titolo',
plugins:[Ext.ux.plugins.RemoteValidator],
rvOptions: {
url: URL.isTitoloUnivoco,
params:{
idCategoria: function(){return Ext.getCmp('myForm').getForm().findField('idCategoria').getValue()}
}
}
}
If you want, you can use my code in plugin.
mgallinucci, thanks for sharing, i had terrible hard time to find a solution for this.
I used your modifications and it worked like a charm.
deeprot
04-13-2009, 04:15 AM
There is one config option for that: remoteValid:true - when you are sure that form loads valid.
Yes, there IS an option as you said, but I'm afraid it won't help in this case since its default value (which is "fault") overrides the one in the config object. I have debugged this case.
So I suggest this solution: instead of
// apply remote validation to field
Ext.apply(field, {
remoteValid:false
// private
,isValid:function(preventMark) {
return isValid.call(this, preventMark) && this.remoteValid;
}
...
I use:
Ext.applyIf(field, {
remoteValid:false
});
Ext.apply(field, {
// private
isValid:function(preventMark) {
return isValid.call(this, preventMark) && this.remoteValid;
}
...
The different thing is when to use the function apply() or applyIf(). The first one seems to override all config options, since the second one simply copies the config options if they are not set.
jsakalos
04-13-2009, 10:53 AM
I've looked in my files and I've found that I do not use this plugin anymore but I use "ServerValidator". I do not have time now to make proper entries, links and demo in forum, anyway, try the following code - I'll post it proper way in a week, or so.
// vim: ts=4:sw=4:nu:fdc=4:nospell
/*global Ext, console */
/**
* @class Ext.ux.form.ServerValidator
* @extends Ext.util.Observable
*
* Server-validates field value
*
* @author Ing. Jozef Sakáloš
* @copyright (c) 2008, by Ing. Jozef Sakáloš
* @date 8. February 2008
* @version 1.0
* @revision $Id: Ext.ux.form.ServerValidator.js 645 2009-03-24 02:35:56Z jozo $
*
* @license Ext.ux.form.ServerValidator is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
* target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
*
* @donate
* <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
* <input type="hidden" name="cmd" value="_s-xclick">
* <input type="hidden" name="hosted_button_id" value="3430419">
* <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-butcc-donate.gif"
* border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
* <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
* </form>
*/
Ext.ns('Ext.ux.form');
/**
* Creates new ServerValidator
* @constructor
* @param {Object} config A config object
*/
Ext.ux.form.ServerValidator = function(config) {
Ext.apply(this, config, {
url:'/request.php'
,method:'post'
,cmd:'validateField'
,paramNames:{
valid:'valid'
,reason:'reason'
}
,validationDelay:500
,validationEvent:'keyup'
,logFailure:true
,logSuccess:true
});
Ext.ux.form.ServerValidator.superclass.constructor.apply(this, arguments);
}; // eo constructor
// extend
Ext.extend(Ext.ux.form.ServerValidator, Ext.util.Observable, {
// {{{
init:function(field) {
this.field = field;
// save original functions
var isValid = field.isValid;
var validate = field.validate;
Ext.apply(field, {
// is field validated by server flag
serverValid: undefined !== this.serverValid ? this.serverValid : true
// serverValid: true
// private
,isValid:function(preventMark) {
if(this.disabled) {
return true;
}
return isValid.call(this, preventMark) && this.serverValid;
}
// private
,validate:function() {
var clientValid = validate.call(this);
// return false if client validation failed
if(!this.disabled && !clientValid) {
return false;
}
// return true if both client valid and server valid
if(this.disabled || (clientValid && this.serverValid)) {
this.clearInvalid();
return true;
}
// mark invalid and return false if server invalid
if(!this.serverValid) {
this.markInvalid(this.reason);
return false;
}
return false;
} // eo function validate
}); // eo apply
// install listeners
this.field.on({
render:{single:true, scope:this, fn:function() {
this.serverValidationTask = new Ext.util.DelayedTask(this.serverValidate, this);
this.field.el.on(this.validationEvent, function(e){
this.field.serverValid = false;
this.filterServerValidation(e);
}, this);
// this.field.el.on({
// keyup:{scope:this, fn:function(e) {
// this.field.serverValid = false;
// this.filterServerValidation(e);
// }}
//// ,blur:{scope:this, fn:function(e) {
//// this.field.serverValid = false;
//// this.filterServerValidation(e);
//// }}
// });
}}
});
} // eo function init
// }}}
,serverValidate:function() {
var options = {
url:this.url + '?#' + (this.name || this.field.name)
,method:this.method
,scope:this
,success:this.handleSuccess
,failure:this.handleFailure
,params:this.params || {}
};
Ext.applyIf(options.params, {
cmd:this.cmd
,field:this.name || this.field.name
,value:this.field.getValue()
,table:this.table
});
Ext.Ajax.request(options);
} // eo function serverValidate
// {{{
,filterServerValidation:function(e) {
if(this.field.value === this.field.getValue()) {
this.serverValidationTask.cancel();
this.field.serverValid = true;
return;
}
if(!e.isNavKeyPress()) {
this.serverValidationTask.delay(this.validationDelay);
}
} // eo function filterServerValidation
// }}}
// {{{
,handleSuccess:function(response, options) {
var o;
try {o = Ext.decode(response.responseText);}
catch(e) {
if(this.logFailure) {
this.log(response.responseText);
}
}
if(true !== o.success) {
if(this.logFailure) {
this.log(response.responseText);
}
}
this.field.serverValid = true === o[this.paramNames.valid];
this.field.reason = o[this.paramNames.reason];
this.field.validate();
} // eo function handleSuccess
// }}}
// {{{
,handleFailure:function(response, options) {
if(this.logFailure) {
this.log(response.responseText);
}
} // eo function handleFailure
// }}}
// {{{
,log:function(msg) {
if(console && console.log) {
console.log(msg);
}
} // eo function log
// }}}
});
Take a look also at docs: http://extjs.eu/docs/?class=Ext.ux.form.ServerValidator
philipz
07-19-2009, 02:53 PM
Dear jsakalos,
Could you post html example of this new version?
Thx!
jsakalos
07-20-2009, 02:40 AM
Yes, however, it is not on top of the priorities list. I plan to revamp my examples and extensions pages and port extensions to Ext 3.x first.
Dave.Sanders
07-26-2009, 09:55 AM
Hey Saki,
I have a suggestion - attached is an updated serverValidate function that you might review and add in. This one allows the user to give ServerValidator a direct function (via a new property called "direct") that uses Ext.Direct to make the call instead of just hitting a url.
I'm converting a project over to Ext.Direct, and figured I would want the validators to work the same way. There is still a TODO to identify and handle failures properly, but it will take a successful Ext.Direct call, turn the result into a faked out response.responseText, and then pass that along to the success function as normal.
Hope its helpful to someone.
serverValidate:function() {
if (this.direct == null) {
var options = {
url:this.url + '?#' + (this.name || this.field.name)
,method:this.method
,scope:this
,success:this.handleSuccess
,failure:this.handleFailure
,params:this.params || {}
};
Ext.applyIf(options.params, {
cmd:this.cmd
,field:this.name || this.field.name
,value:this.field.getValue()
,table:this.table
});
Ext.Ajax.request(options);
} else {
this.direct.call(this, this.field.getValue(), function(e) {
var response={responseText:e};
this.handleSuccess(response);
// TODO: identify and handle failure...
}, this);
}
}
I snagged the code to apply this to off of your manual page, so hopefully that is the latest.
jsakalos
07-26-2009, 04:44 PM
Thank you very much. I'll most likely migrate my app to direct too (well, it's too big so the decision has not been made yet).
Dave.Sanders
07-27-2009, 02:46 PM
Saki,
Two other things I bumped into in implementing this version over the RemoteValidator:
1. It would be helpful to have a "data" property that I can specify in paramNames, which gets put onto the field. So, in my copy I've set it up like so in handleSuccess:
this.field.validData = o[this.paramNames.data];
So, I can pass along some data with the validation call that then goes onto field.validData.
2. I added a "beforevalidate" event that goes onto the field during the init. This then gets fired right at the top of serverValidate.
In my case, I wanted to be able to put a message up before the server communication started (or to set up a mask, or to run an animation, etc.) so I tap into beforevalidate, then use the valid, invalid events to hide my message.
I've added these to my version, but again, it might be helpful for others to have in the plugin proper.
Thanks!
Dave
Dave.Sanders
07-27-2009, 03:38 PM
Actually, Valid and Invalid events on the field are being called too often for my use. I think the plugin should create two new events on the Field called "beforeValidate" and "afterValidate". These seem to suit at least my purposes better: setting up stuff to happen before the server call, and then cleaning up after those things afterwards.
Just a thought
Dave
MichaelOstrovsky
08-30-2009, 09:08 AM
i have modified the plugin a bit to allow setting initial 'remote valid' state. for example, when loading a form from db, its not nice to show 'not verified yet' right ahead.
now, you can set 'remoteValid' property initially in field.
...
Ext.ux.plugins.RemoteValidator = {
init:function(field) {
// save original functions
var isValid = field.isValid;
var validate = field.validate;
// apply remote validation to field
Ext.apply(field, {
remoteValid:!!field.remoteValid //Michael
// private
,isValid:function(preventMark) {
return isValid.call(this, preventMark) && this.remoteValid;
}
...
jsakalos
08-30-2009, 02:06 PM
Thank you for the patch.
x5150
09-01-2009, 01:55 PM
Is it supposed to work with file uploads also? I have it working with the following code but does not validate when uncommenting inputType.
xtype: 'textfield',
fieldLabel: 'Select File to Upload',
//inputType: 'file',
autoCreate: {tag: "input", type: "text", size: "60", autocomplete: "off"},
plugins:[new Ext.ux.form.ServerValidator({
url:'foo',
params:{foo:bar}
} )],
Dave.Sanders
09-01-2009, 03:24 PM
Saki, possibly another bug:
I think filterServerValidation needs to check for blank fields and disregard the validation if the field is allowBlank:true. I was having some problems when I was tabbing through a set of fields where one of the fields was a remote validator, but it was ok to be blank. (basically, I only validate IF they enter something.)
I changed filterServerValidation to this:
,filterServerValidation:function(e) {
if(this.field.value === this.field.getValue() ||
(this.field.getValue() == "" && this.field.allowBlank)) {
this.serverValidationTask.cancel();
this.field.serverValid = true;
return;
}
if(!e.isNavKeyPress()) {
this.serverValidationTask.delay(this.validationDelay);
}
}
jsakalos
09-01-2009, 04:16 PM
Take a look at http://extjs.eu/docs/?class=Ext.ux.form.ServerValidator
x5150
09-01-2009, 04:41 PM
Take a look at http://extjs.eu/docs/?class=Ext.ux.form.ServerValidator
What am I looking for?
x5150
09-02-2009, 06:37 PM
I don't know what you are referring to in the docs, there isn't an example with file upload types and not much else there. I've tried changing the validateEvent to 'change' and 'blur' but no async call. Please help.
jsakalos
09-03-2009, 04:07 AM
@x5150,
I haven't tried file upload fields with the validator. The first questions to answer would be:
1. does field upload field fire events as text field? If not, then there is little chance to make it working.
2. what getValue() returns?
x5150
09-03-2009, 12:20 PM
@x5150,
I haven't tried file upload fields with the validator. The first questions to answer would be:
1. does field upload field fire events as text field? If not, then there is little chance to make it working.
2. what getValue() returns?
1. yes it does fire at least a 'change' event after file selection
2. returns the filename
jsakalos
09-03-2009, 07:59 PM
So if you set validationEvent:'change' it should work... If not, can you post a showcase?
vBulletin® v3.8.4, Copyright ©2000-2009, Jelsoft Enterprises Ltd.