PDA

View Full Version : [New] Remote Field Validation Plugin



jsakalos
25 Nov 2007, 9:14 AM
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
27 Nov 2007, 5: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
28 Nov 2007, 1:15 AM
Yes, you're right. It's some stray code. I'll remove it.

Tasm
28 Nov 2007, 4:53 PM
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
29 Nov 2007, 4: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
29 Nov 2007, 8:35 AM
Thanks for ideas. I'll consider all of 'em in next version.

Cheers,
saki

JorisA
4 Dec 2007, 5: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
5 Dec 2007, 5: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
5 Dec 2007, 12: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
5 Dec 2007, 12: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
6 Dec 2007, 2: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 Dec 2007, 6: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 Dec 2007, 8: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
14 Dec 2007, 4: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
14 Dec 2007, 12: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
15 Dec 2007, 2: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
16 Dec 2007, 1: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
17 Dec 2007, 12:29 AM
Yes, you're right. Thank's for debugging.

attiato
18 Jan 2008, 4: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
18 Jan 2008, 7:38 AM
I posted your code into one of my forms (which happens to exist upon a Window) and it works for me.

anjelika
19 Feb 2008, 8: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
19 Feb 2008, 8: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
19 Feb 2008, 10:12 AM
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
19 Feb 2008, 10:45 AM
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
3 Mar 2008, 7: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
3 Mar 2008, 9:20 AM
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
3 Mar 2008, 12: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
3 Mar 2008, 12:16 PM
Yeah, just you don't need single:false - it's default but that's just cosmetics.

omegafox
27 Mar 2008, 3:12 PM
is it possible to use this plugin for cross validations with two date fields and numberfields?

jsakalos
27 Mar 2008, 5: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
28 Mar 2008, 4:28 AM
nice plug-in and looks very useful, could some please show an ASP example of a simple validation?

Thanks!

jsakalos
28 Mar 2008, 4:38 AM
Unfortunately not, because I do not use Micro$oft "products".

chiru
31 Mar 2008, 11:15 PM
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
1 Apr 2008, 4: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
3 Apr 2008, 7: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
3 Apr 2008, 8:04 AM
This looks like the problem is outside of the validator. Easiest is to give field ids and then Ext.getCmp('that-id').getValue()

omegafox
3 Apr 2008, 10:33 AM
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
3 Apr 2008, 12: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
2 May 2008, 3: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
3 May 2008, 2:38 AM
If you load values from server you are sure are valid you can pass config option remoteValid:true.

DaNCeT
10 May 2008, 2: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
10 May 2008, 2:46 AM
Yes, you're right; this way validator honors validation event set on field. Updating source.

DaNCeT
11 May 2008, 3: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
11 May 2008, 4: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
11 May 2008, 5:12 AM
Difficult to say... I validate combos and dates w/o problems...

Is the request sent to server? What comes back?

DaNCeT
11 May 2008, 10:52 AM
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
11 May 2008, 12: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
11 May 2008, 3: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
11 May 2008, 10:26 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.

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
12 May 2008, 1:26 AM
Well, then you need to hack it somehow, to add another events that trigger validation.

malord
13 May 2008, 1: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
14 May 2008, 11:00 AM
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
15 May 2008, 1: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
26 May 2008, 2: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
27 May 2008, 2: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
7 Jun 2008, 9:00 AM
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
8 Jun 2008, 4:55 AM
There is one config option for that: remoteValid:true - when you are sure that form loads valid.

yanick
17 Jun 2008, 5: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
18 Jun 2008, 3: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
18 Jun 2008, 1: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
18 Jun 2008, 3:35 PM
You'd need to hack the code then...

battisti
19 Jun 2008, 3:27 AM
thx i will do it

battisti
19 Jun 2008, 6: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
8 Jul 2008, 6: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
8 Jul 2008, 10:00 PM
The plugin is not class, it is singleton object therefore now new keyword is required/allowed.

illuminum
9 Jul 2008, 3:33 AM
Makes sense. A new pattern to add to my utility-belt--thanks.

LeandroC
4 Aug 2008, 11:32 AM
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
4 Aug 2008, 12:47 PM
Any picture and/or code?

LeandroC
4 Aug 2008, 6: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
5 Aug 2008, 12: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
5 Aug 2008, 10:35 AM
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
30 Aug 2008, 5: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
30 Aug 2008, 11:07 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.

thephatp
31 Aug 2008, 7: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
17 Sep 2008, 4: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
18 Sep 2008, 12: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
20 Sep 2008, 2: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
20 Sep 2008, 2:58 PM
I have it keyup.

hAmpzter
21 Sep 2008, 11:34 PM
Ahhh, that would maybe work better! :) Thx!

timb
22 Sep 2008, 10:10 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.

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
22 Sep 2008, 11:21 AM
There was one bug pointed out a couple of posts back. Take the code now it's been fixed.

hAmpzter
23 Sep 2008, 12: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
25 Sep 2008, 8:51 AM
"Ext.ux.form is undefined" when using the successor of RemoteValidator.

:-?

jsakalos
25 Sep 2008, 11:05 AM
Add Ext.ns('Ext.ux.form'); at the beginning of the code.

damsfx
26 Sep 2008, 12: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
9 Oct 2008, 7: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
12 Oct 2008, 11:55 PM
{"success":false, "errors":"this is bad value"}

mgallinucci
27 Feb 2009, 1: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
27 Feb 2009, 2:12 AM
Thanks for sharing. Maybe it helps others with a similar problem.

pludikhu
5 Mar 2009, 1: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
5 Mar 2009, 1:58 PM
No idea. I have no clue what is that other extension.

attiato
8 Mar 2009, 4: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
13 Apr 2009, 12: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
13 Apr 2009, 6: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
19 Jul 2009, 10:53 AM
Dear jsakalos,

Could you post html example of this new version?
Thx!

jsakalos
19 Jul 2009, 10:40 PM
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
26 Jul 2009, 5: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
26 Jul 2009, 12: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
27 Jul 2009, 10:46 AM
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
27 Jul 2009, 11:38 AM
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
30 Aug 2009, 5: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
30 Aug 2009, 10:06 AM
Thank you for the patch.

x5150
1 Sep 2009, 9:55 AM
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
1 Sep 2009, 11:24 AM
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
1 Sep 2009, 12:16 PM
Take a look at http://extjs.eu/docs/?class=Ext.ux.form.ServerValidator

x5150
1 Sep 2009, 12:41 PM
Take a look at http://extjs.eu/docs/?class=Ext.ux.form.ServerValidator

What am I looking for?

x5150
2 Sep 2009, 2: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
3 Sep 2009, 12: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
3 Sep 2009, 8:20 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?

1. yes it does fire at least a 'change' event after file selection

2. returns the filename

jsakalos
3 Sep 2009, 3:59 PM
So if you set validationEvent:'change' it should work... If not, can you post a showcase?

ladro1987
21 May 2010, 6:59 AM
Hi,
I have uses this plugin for the remote validation


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


This is my textfield:


xtype:'textfield',
fieldLabel: 'E-mail',
name: 'email',
vtype:'email',
vtypeText: 'Inserisci un\'email valida',
anchor:'95%',
blankText:'Inserisci la tua <b>email</b>',
msgTarget: 'under',
allowBlank: false,
plugins:[new Ext.ux.form.ServerValidator({
url:'valid/ins_email_check.php'
} )]
/*plugins:[Ext.ux.plugins.foServerValidator],
rvOptions: {
url:'valid/ins_email_check.php'
}*/
And this is some of my php code:



$post = $_POST;

$field = @$post["field"];
$value = @$post["value"];

$o = new stdClass;
$o->success = true;
$o->valid = false;

$sql="
SELECT nome
FROM utents
WHERE username='".$value."'
";
$query=mysql_query($sql) or die("Errore SQL: ".mysql_error()."<br />".dbg_box($sql));
if (!mysql_num_rows($query)){
$o->valid = true;
unset($o->reason);
}else
$o->reason = "Username Exist";

header("Content-Type: application/json");
echo json_encode($o);

The problem is that if the username not exist into the table (condition without errors), it show the error's message "The value in this field is invalid".

If show the error's message present into "reason" (Username Exist), it show this message also when the username not exist.
Don't reset the reason?

I have upgrade the plugin but not the PHP code.

Into the PHP code change the sintax?

Thanks

Roberto.

jsakalos
21 May 2010, 12:06 PM
Javascript of the plugin reacts on the basis of response received from the server. Return responses that reflect your statuses and everything will be OK.

Bleak
25 Aug 2010, 6:07 AM
I had an issue with the ServerValidator always sending the original value into the options.params.value. I believe it was related to this function



Ext.applyIf(options.params, {
cmd:this.cmd
,field:this.name || this.field.name
,value:this.field.getValue()
,table:this.table
});
As any subsequent calls would already have a value attribute in the params object. I changed it to use Ext.apply.. instead of Ext.applyIf.



Ext.apply(options.params, {
cmd:this.cmd
,field:this.name || this.field.name
,value:this.field.getValue()
,table:this.table
});
Unless I am missing something with how I call it, which is as follows;



plugins : [new Ext.ux.form.ServerValidator({
url : 'pp.do',
params : {ACTION: 'ValidateNewProjectName', xaction: 'read', entity: 'subscriber'}
})]

jsakalos
25 Aug 2010, 6:22 AM
I've never run into that problem because I've never set this.params. Anyway, it is a bug that is fixed by your change. Thank you.

masood
10 Jun 2011, 5:10 PM
Hi
Im a newbie to extjs. This plugin works great and thanx for creating it.
One issue I seem to be having is with the remoteValid flag. It doesnt seem to change the behavior even if I set it to true or false. In order to get it to work I changed the the following in the plugin:


Ext.apply(field, {
remoteValid: field.remoteValid || false
...


Is this the correct way to do it? Or am i missing something?

xplain
13 Jun 2011, 11:07 PM
Is the plugin compatible with extjs 4? If not can someone rewrite it for extjs 4

yyogev
28 Jun 2012, 2:35 AM
to make the validation work in ExtJS 4, I replaced

var clientValid = validate.call(this);
with

var clientValid = isValid.call(this);

I am not very familiar with the inner workings of this class, so I'd be hapy to hear your comments on this change.