{"id":3251,"date":"2010-01-12T19:45:31","date_gmt":"2010-01-12T18:45:31","guid":{"rendered":"http:\/\/www.chipwreck.de\/blog\/?p=3251"},"modified":"2016-12-31T02:12:17","modified_gmt":"2016-12-31T01:12:17","slug":"mootools-formvalidator-how-to-use-part-3","status":"publish","type":"post","link":"https:\/\/www.chipwreck.de\/blog\/2010\/01\/12\/mootools-formvalidator-how-to-use-part-3\/","title":{"rendered":"Mootools FormValidator \u2013 How to use (Part 3)"},"content":{"rendered":"<div class=\"contentnavi\">\n<p class=\"contentnav1 center\">\n<a href=\"\/blog\/2009\/12\/14\/mootools-formvalidator-how-to-use-part-1\/\">Tutorial Part 1<\/a> &bull;<br \/>\n<a href=\"\/blog\/2009\/12\/28\/mootools-formvalidator-how-to-use-part-2\/\">Part 2<\/a> &bull;<br \/>\n<span class=\"pink\">Part 3<\/span> &bull;<br \/>\n<a href=\"\/blog\/2010\/01\/19\/mootools-formvalidator-how-to-use-part-4\/\">Part 4<\/a> &bull;<br \/>\n<a href=\"\/blog\/2009\/12\/23\/mootools-formvalidator-demo\/\">Live demo<\/a>\n<\/p>\n<\/div>\n<p>This tutorial part is about advanced custom validators and properties &#8211; and how to use them with a (pseudo-)ajax call.<!--more--><\/p>\n<h2>More about custom validators<\/h2>\n<p>In <a href=\"\/blog\/2009\/12\/28\/mootools-formvalidator-how-to-use-part-2\/\">Part 2<\/a> we created a custom validator, which tests for numbers and letters &#8211; a simple regular expression. But in real life there are often more complex criteria involved.<\/p>\n<p>Let&#8217;s say in our registration form, we&#8217;d like each user to have a unique email-address. So the validator should not only check if the entered email address is valid (syntactically) but also query the (fictional) user database &mdash; to find out if the email is not yet registered.<\/p>\n<p>Therefore we need the following:<\/p>\n<ul>\n<li>A page to tell us if a given email address is already registered<\/li>\n<li>A custom validator which sends the entered email address to this page<\/li>\n<\/ul>\n<p>The page itself (<kbd>formvalidator-ajax.php<\/kbd>) is written in PHP and looks like this:<\/p>\n<pre lang=\"php\">\r\n&lt;?php\r\ninclude('...'); \/\/ include the required framework classes etc.\r\n$mail = isset($_REQUEST['mail']) ? $_REQUEST['mail'] : false;\r\n\r\nif (User::emailExists($mail)) {\r\n\techo '1';\r\n}\r\nelse {\r\n\techo '0';\r\n}\r\n?&gt;\r\n<\/pre>\n<p class=\"small\">I won&#8217;t go into any details here since we&#8217;re talking about Mootools, not PHP &#8211; but simply put I assume a static method <kbd>User::emailExists($which)<\/kbd> exists, which checks if a given email address is already present in the database and returns true or false. Of course the input has to be filtered against injections etc. but this happens behind the scenes.<\/p>\n<p>This simple page receives the parameter <kbd>mail<\/kbd> via GET or POST and returns &#8220;1&#8221; if the email exists, otherwise &#8220;0&#8221;.<\/p>\n<p>So we can check the existence by calling <kbd>http:\/\/yourdomain.org\/formvalidator-ajax.php?mail=test@test.de<\/kbd><\/p>\n<p>Now we build another custom validator, called &#8220;emailUnique&#8221;, which uses the Request()-class from Mootools to access this page:<\/p>\n<pre lang=\"js\">\r\nFormValidator.add('emailUnique', {\r\n\terrorMsg: 'E-Mail address is already registered',\r\n\ttest: function(element, props) {\r\n\t\tif (element.value.length > 0) {\r\n\t\t\tvar req = new Request({\r\n\t\t\t\turl: '\/cwcrop\/formvalidator-ajax.php',\r\n\t\t\t\tasync: false\r\n\t\t\t}).send(\"mail=\" + element.value);\r\n\t\t\treturn (req.response.text != '1');\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n});\r\n<\/pre>\n<p>Have a look at the test()-method:<\/p>\n<p>It calls an URL <em>synchronously<\/em> (so <q>ajax<\/q> is a bit misleading) and appends the parameter mail as GET-Parameter. The value is of course the content of the input field (<kbd>element.value<\/kbd>).<\/p>\n<p>Since this request is synchronous we don&#8217;t have to use callbacks. We can directly handle the response from the requested page &mdash; if our response is <em>not<\/em> equal to &#8220;1&#8221;<br \/>\nthe validation was successful (=email can be used).<\/p>\n<h4>Error handling, security and convenience<\/h4>\n<p>A synchronous request has one big disadvantage: It waits for the request to end, so if the connection is extremly slow or times out, the script waits as long as this takes. In a high traffic environment you better use an asynchronous request.<\/p>\n<p>Note the &#8220;<kbd>return true;<\/kbd>&#8221; at the end: This is the fallback. If the page does not return anything we optimistically assume the email address is valid.<\/p>\n<p>But can&#8217;t this lead to problems?<\/p>\n<p>No! Since it&#8217;s <strong>absolutely necessary<\/strong> to validate all input a second time via PHP before inserting it into the database! The FormValidator is convenient, but not secure (simply turn Javascript off &#8230;).<br \/>\nSo our fallback does the right thing: It simply delays the validation to the PHP part and in the between time the user can go on.\n<\/p>\n<p>If we had used &#8220;<kbd>return false;<\/kbd>&#8221; as fallback and the requested page had a problem, the user would always get an error message, regardless of her input &#8211; not a good way to convince user to register..<\/p>\n<h2>Using properties<\/h2>\n<p>If you have a user database and a registration form you surely will also have a &#8220;profile&#8221;-page, where a registered user can change her data.<\/p>\n<p>This page is usually quite similar to a registration form with all data already filled in. But what about our emailUnique-validator? It doesn&#8217;t work &#8211; because if the user does not change the email address she gets an error, since her own email address is of course already present in the database.<\/p>\n<p>But lazy as we are we don&#8217;t want to write a second validator, we want to reuse the existing one.<\/p>\n<p>And this is also quite simple: We add a second parameter to the database query &mdash; the user-id. If there is no user-id then we are in the registration process and everything stays the same. But if a user-id is present (=the user is already in the database) we&#8217;re going to check the email against the database <em>except<\/em> the row with this user-id.<\/p>\n<h4>Email uniqueness v2<\/h4>\n<pre lang=\"php\">\r\n&lt;?php\r\ninclude('...'); \/\/ include the required framework classes etc.\r\n$mail = isset($_REQUEST['mail']) ? $_REQUEST['mail'] : false;\r\n$uid = isset($_REQUEST['uid']) ? $_REQUEST['uid'] : false;\r\n\r\nif (User::emailExists($mail, $uid)) {\r\n\techo '1';\r\n}\r\nelse {\r\n\techo '0';\r\n}\r\n?&gt;\r\n<\/pre>\n<p>So we add a second parameter (<kbd>uid<\/kbd>, short for user-id) and the database query ignores the appropriate row &mdash; if we pass a valid user-id to this method.<\/p>\n<p>And we want to recycle our validator on the profile page, so we need a way to pass an additional information to it: The user-id. That&#8217;s what properties are for.<\/p>\n<p>Properties are simple key-value pairs which are written into the HTML class-attribute like this:<\/p>\n<pre lang=\"html\">\r\n &lt;input class=\"minLength:10\"&gt;\r\n<\/pre>\n<p>In our case we add the property &#8220;userId&#8221;, so the email field on the profile page looks like this:<\/p>\n<pre lang=\"html\">\r\n &lt;input class=\"emailUnique userId:14 validate-email\" type=\"text\" name=\"profile[email]\" value=\"any@any.org\" \/&gt;\r\n<\/pre>\n<p class=\"small\">Of course the number 14 and the value are dynamically written there by a PHP method.<\/p>\n<p>And here&#8217;s how the validator looks with properties:<\/p>\n<pre lang=\"js\">\r\nFormValidator.add('emailUnique', {\r\n\terrorMsg: 'E-Mail address is already registered',\r\n\ttest: function(element, props) {\r\n\t\tif (element.value.length > 0) {\r\n\t\t\tvar uid = '';\r\n\t\t\tif ($type(props.userId)) {\r\n\t\t\t\tuid = props.userId;\r\n\t\t\t}\r\n\t\t\tvar req = new Request({\r\n\t\t\t\turl: '\/cwcrop\/formvalidator-ajax.php',\r\n\t\t\t\tasync: false\r\n\t\t\t}).send(\"mail=\" + element.value + \"&amp;uid=\" + uid);\r\n\t\t\treturn (req.response.text != '1');\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n});\r\n<\/pre>\n<p>So we append a second parameter (uid) to our request &mdash; which of course can be empty (that&#8217;s the case on the registration form.<\/p>\n<p>The only thing we need to do is to look if this property is present and if so, read it. And therefore the second parameter of the test()-method is used &#8211; it&#8217;s an object with <em>all<\/em> properties present in the given element.<br \/>\nOkay: We look if the userId field is present in the properties and put it into the variable <kbd>uid<\/kbd> (which by default is empty) and append this to our URL. And ready.<\/p>\n<p class=\"small\">The property values are JSON-like encoded, see the mootools documentation for more information.<\/p>\n<h2>Done (well not really)<\/h2>\n<p>Comments, remarks and criticism are welcome! But don&#8217;t miss the additional <a href=\"\/blog\/2010\/01\/19\/mootools-formvalidator-how-to-use-part-4\/\">part 4 &raquo;<\/a><\/p>\n<h4><strong>Comments\/Feedback? Now collected in <a href=\"\/blog\/2010\/01\/19\/mootools-formvalidator-how-to-use-part-4\/\">part 4 &raquo;<\/a><\/strong><\/h4>\n","protected":false},"excerpt":{"rendered":"<p>Tutorial Part 1 &bull; Part 2 &bull; Part 3 &bull; Part 4 &bull; Live demo This tutorial part is about advanced custom validators and properties &#8211; and how to use them with a (pseudo-)ajax call.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[14],"tags":[55,10,54],"class_list":["post-3251","post","type-post","status-publish","format-standard","hentry","category-javascript","tag-javascript-mootools","tag-mootools","tag-track"],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/paPEN-Qr","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/posts\/3251","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/comments?post=3251"}],"version-history":[{"count":0,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/posts\/3251\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/media?parent=3251"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/categories?post=3251"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/tags?post=3251"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}