Actions

Talk

Difference between revisions of "Client-side form validation"

From Joomla! Documentation

(New page: == Validation works, but.. == On a component of my own in backend, this makes the validation, returns the error, but data in the form are lost: function save() { global $mainframe; ...)
 
m (moved Talk:Form validation to Talk:Client-side form validation: Adjusted title to be more specific)
 
(9 intermediate revisions by 5 users not shown)
Line 8: Line 8:
 
   JRequest::checkToken() or jexit( 'Invalid Token' );
 
   JRequest::checkToken() or jexit( 'Invalid Token' );
 
   $email = JRequest::getString('email', ''); // start email validation
 
   $email = JRequest::getString('email', ''); // start email validation
   if($email != '') // email is not required but if isset must be valid
+
   if($email != null) // email is not required but if isset must be valid
 
   {
 
   {
 
   jimport( 'joomla.mail.helper' );
 
   jimport( 'joomla.mail.helper' );
Line 27: Line 27:
  
 
([[User:Dangerfield|Dangerfield]] 19:58, 13 March 2009 (UTC))
 
([[User:Dangerfield|Dangerfield]] 19:58, 13 March 2009 (UTC))
 +
 +
== Add "validate" to the button class ==
 +
 +
I think this is a great feature in the Joomla 1.5, and wish more developers implemented it in their forms.
 +
 +
The best example of this in action is on the Joomla 1.5 registration form. \components\com_user\views\register\tmpl\default.php.
 +
 +
I am not sure why they left out adding "validate" to the button class, but it is essential to performing the validation on submit.
 +
 +
== Is the code example in "Really only accept form after validation" wrong? ==
 +
I'm new to Joomla, so I don't know if this is something that changed recently, but, at least when using JHTML::_('behavior.formvalidation'), the example shown in that section does not work as one would expect.
 +
Namely, the function myValidate(f) is not used.
 +
 +
This seems to be because in validation.js, the attachToForm function overwrites the "onclick" value of all inputs/buttons of type "submit". Hence the form is validated in the first place when the button itself is clicked.
 +
So if the validation is wrong, the value in "onSubmit" (and therefore myValidate) will never be used.
 +
 +
Am I missing something here? Otherwise I think we should change the example.
 +
 +
([[User:rodrigo_i_s|rodrigo_i_s]])
 +
 +
== Validation vs Toolbar ==
 +
 +
I am trying to use this validation in a form with the standard toolbar. Everything is working fine, until the user clicks a toolbar button.
 +
 +
The toolbar buttons '''do submit''' the form, even the '''Cancel''' button. Thus in the function ''myValidate()'' You have to check for '''task == cancel''' before validation, or get the message.
 +
 +
However, when clicked other buttons, the validation shows the message, but '''still submits the form'''. Tried to empty the field '''task''', but without success.
 +
 +
--[[User:UsagiYojimbo|UsagiYojimbo]] 09:24, 19 October 2009 (UTC)
 +
 +
Found a solution:
 +
 +
  function submitbutton(pressbutton) {
 +
    var f = document.adminForm;
 +
    if (pressbutton == "cancel") {
 +
      submitform(pressbutton);
 +
    }
 +
    else if (document.formvalidator.isValid(f)) {
 +
      submitform(pressbutton);
 +
    }
 +
    else {
 +
      alert("Some values are not acceptable. Please check them.");
 +
      f.task.value = "";
 +
    }
 +
  }
 +
 +
--[[User:UsagiYojimbo|UsagiYojimbo]] 12:14, 29 October 2009 (UTC)
 +
 +
== Override the check() function in your class that extends the JTable ==
 +
 +
If the submittion of a form stores a row in your database, you can also override the check() function in your class that extends the JTable (lets call it Yourtable).
 +
 +
<source lang="php">
 +
// joomla/administration/components/com_yourcomponent/tables/yourtable.php
 +
 +
class YourtableTable extends JTable {
 +
 +
    /* e.g. a number that should be >0 */
 +
    var $num = null;
 +
 +
    var $...
 +
 +
    // ...
 +
 +
    // perform the check here, and act apropriately
 +
    function check() {
 +
        if ($this->num < 0) {
 +
          JError::raiseError(500, 'num can not be less than 0');
 +
          return false;
 +
        }
 +
        // ...
 +
        return true;
 +
    }
 +
}
 +
</source>
 +
 +
 +
In your controller first bind() the form' s data with your table object, afterwords check() and then store()
 +
 +
<source lang="php">
 +
/* joomla/components/com_yourcomponent/controller.php */
 +
 +
class YourcontrollerController extends JController {
 +
 +
  /* the default display */
 +
  function display() {
 +
  /* do smtg, e.g. call a view, a layout, a model... */
 +
  }
 +
 +
  /* activated when task=save */
 +
  function save() {
 +
    $row = & JTable::getInstance('Yourtable', 'Table');
 +
 +
    // ...
 +
 +
    if (! $row->bind($row)) {
 +
JError::raiseError(500, $row->getError());
 +
return false;
 +
    }
 +
 +
    // ...
 +
 +
    if (! $row->check($row)) {
 +
JError::raiseError(500, $row->getError());
 +
return false;
 +
    }
 +
 +
    // ...
 +
    if (! $row->store($data)) {
 +
JError::raiseError(500, $row->getError());
 +
return false;
 +
    }
 +
 +
    // ...
 +
}
 +
</source>
 +
 +
Remember to place the task as hidden value in your form:
 +
 +
<source lang="php">
 +
/* joomla/com_yourcomponent/views/yourview/tmpl/default.php */
 +
 +
...
 +
<form action="index.php" method="post">
 +
  ...
 +
  <input type="text" name="num" id="num" value="" size="4" />
 +
 +
  <input type="hidden" name="task" value="save" />
 +
</form>
 +
</source>
 +
 +
 +
Alternatively, override the store() function to call check() or perform the
 +
actual checks in your table class (YourtableTable).

Latest revision as of 08:21, 12 June 2011

Contents

Validation works, but..

On a component of my own in backend, this makes the validation, returns the error, but data in the form are lost:

function save()
{
 global $mainframe;
 JRequest::checkToken() or jexit( 'Invalid Token' );
 $email = JRequest::getString('email', ); // start email validation
 if($email != null) // email is not required but if isset must be valid
 {
 jimport( 'joomla.mail.helper' );
     if (!JMailHelper::isEmailAddress($email))
     {
     $mainframe->enqueueMessage('Email not valid', 'error');
     return $this->execute('edit');
     }
  }
  $row =& JTable::getInstance('mytable', 'Table');          
  if (!$row->bind(JRequest::get('post'))) 
     {
     JError::raiseError(500, $row->getError() );
     }
}  

What's wrong here? Any suggestion to retrieve the data that I was filling before the validation stop..?

(Dangerfield 19:58, 13 March 2009 (UTC))

Add "validate" to the button class

I think this is a great feature in the Joomla 1.5, and wish more developers implemented it in their forms.

The best example of this in action is on the Joomla 1.5 registration form. \components\com_user\views\register\tmpl\default.php.

I am not sure why they left out adding "validate" to the button class, but it is essential to performing the validation on submit.

Is the code example in "Really only accept form after validation" wrong?

I'm new to Joomla, so I don't know if this is something that changed recently, but, at least when using JHTML::_('behavior.formvalidation'), the example shown in that section does not work as one would expect. Namely, the function myValidate(f) is not used.

This seems to be because in validation.js, the attachToForm function overwrites the "onclick" value of all inputs/buttons of type "submit". Hence the form is validated in the first place when the button itself is clicked. So if the validation is wrong, the value in "onSubmit" (and therefore myValidate) will never be used.

Am I missing something here? Otherwise I think we should change the example.

(rodrigo_i_s)

Validation vs Toolbar

I am trying to use this validation in a form with the standard toolbar. Everything is working fine, until the user clicks a toolbar button.

The toolbar buttons do submit the form, even the Cancel button. Thus in the function myValidate() You have to check for task == cancel before validation, or get the message.

However, when clicked other buttons, the validation shows the message, but still submits the form. Tried to empty the field task, but without success.

--UsagiYojimbo 09:24, 19 October 2009 (UTC)

Found a solution:

 function submitbutton(pressbutton) {
   var f = document.adminForm;
   if (pressbutton == "cancel") {
     submitform(pressbutton);
   }
   else if (document.formvalidator.isValid(f)) {
     submitform(pressbutton);
   }
   else {
     alert("Some values are not acceptable. Please check them.");
     f.task.value = "";
   }
 }

--UsagiYojimbo 12:14, 29 October 2009 (UTC)

Override the check() function in your class that extends the JTable

If the submittion of a form stores a row in your database, you can also override the check() function in your class that extends the JTable (lets call it Yourtable).

// joomla/administration/components/com_yourcomponent/tables/yourtable.php
 
class YourtableTable extends JTable {
 
    /* e.g. a number that should be >0 */
    var $num = null; 
 
    var $...
 
    // ...
 
    // perform the check here, and act apropriately 
    function check() {
        if ($this->num < 0) {
           JError::raiseError(500, 'num can not be less than 0');
           return false;
        } 
        // ...
        return true;
    }
}


In your controller first bind() the form' s data with your table object, afterwords check() and then store()

/* joomla/components/com_yourcomponent/controller.php */ 
 
class YourcontrollerController extends JController {
 
  /* the default display */
  function display() {
   /* do smtg, e.g. call a view, a layout, a model... */
  }
 
  /* activated when task=save */
  function save() {
    $row = & JTable::getInstance('Yourtable', 'Table');
 
    // ...
 
    if (! $row->bind($row)) {
        JError::raiseError(500, $row->getError());
        return false;
    }
 
    // ...
 
    if (! $row->check($row)) {
        JError::raiseError(500, $row->getError());
        return false;
    }
 
    // ...
    if (! $row->store($data)) {
        JError::raiseError(500, $row->getError());
        return false;
    }
 
    // ...
}

Remember to place the task as hidden value in your form:

/* joomla/com_yourcomponent/views/yourview/tmpl/default.php */
 
...
<form action="index.php" method="post"> 
  ... 
  <input type="text" name="num" id="num" value="" size="4" />
 
  <input type="hidden" name="task" value="save" />
</form>


Alternatively, override the store() function to call check() or perform the actual checks in your table class (YourtableTable).