Archive for July, 2010

jquery form validation with cakephp model validation

I am currently working on a project in CakePHP and have used the jQuery form validation plugin from Jorn Zaefferer on other non-cake projects. So I had a thought… wouldn’t it be nice to do the field validation right from the cake model validation rules. So this is what I came up with.

[Warning Rough Draft!]

In my default layout I added the includes to load jQuery, jQuery Validate, and metadata. (Mine are inside an if condition that I activate on a per view basis, but this would be for application wide use.

echo $this->Html->script('jquery');
echo $this->Html->script('jquery-validate/jquery.validate.min');
echo $this->Html->script('jquery-validate/lib/jquery.metadata');

In the User model (/app/models/user.php) file I added a rule and made sure that it was working:

var $validate = array(
	    'firstName' => array(
	        'rule' => '/^[a-zA-Z\x27]{2,}$/i', //2 letters or '
	        'message' => 'First Name must only contain letters, and be at least two characters.'
	    'lastName' => array(
	        'rule' => '/^[a-zA-Z\x27]{2,}$/i', //2 letters or '
	        'message' => 'First Name must only contain letters, and be at least two characters.'

In the controller (/app/controllers/users_controller.php) I added the request handler componet. As well as the function ajax_validate. The function tries to create a new instance of the User model with the data provided. It then calls $this->User->validates() to see if it passes validation. If not the cake model error will be returned and added to the error label for user feedback.

var $helpers = array('Html','Ajax','Javascript'); //these are the helpers I am using
var $components = array('RequestHandler');

	function ajax_validate(){
		Configure::write('debug', 0); 
		$this->autoRender = false;
		$ret = "false";
		$this->data = $_GET['data'];
		if ($this->RequestHandler->isAjax()) {
		// If we have data, process it. If not send back an error.
				// $this->cleanUpFields();
				// Validate the User, if it's ok, show no errors. If not ok, show errors
				if ($this->User->validates()){
	                		$ret = true;
	            		} else {
	            			$errors = $this->User->invalidFields();
	            			// grab the error message from the array
	            			$ret = '';
	            			foreach($errors as $error){
	            				$ret .= $error;
			echo json_encode($ret);
		} else {
			echo 'not_ajax';

In the view (/app/views/users/index.ctp) I added the form validation jQuery initialization code as well as a form for the user to edit their settings. I am using the form meta plug-in to grab the validation rule out of the class parameter on the form field. So in the class, I add a remote remote:’users/ajax_validate’, so that jQuery will look to the controller function ajax_validate() to validate the field.

<div class="users form">
<?php echo $this->Form->create('User');?>
 		<legend><?php __('My Settings'); ?>Form->input('id');
		echo $this->Form->input('userName', array('label' => 'Username', 'disabled'=>'disabled'));// (not edit-able) 
		<?php echo $this->Form->input('firstName', array('class' => "{validate:{required:true,remote:'users/ajax_validate'}}"));?>
		<p class="subtle ml10 mbl1em">( your first name)</p>
		<?php echo $this->Form->input('lastName', array('class' => "{validate:{required:true,remote:'users/ajax_validate'}}")); ?>
		<p class="subtle ml10 mbl1em">( your last name)</p>
		<?php echo $form->submit('Save');?>

<?php //extra javascript for this view
echo $javascript->codeBlock('

$(document).ready(function() { 
    	onsubmit: false, //otherwise it will do all the remote calls when the user hits submit
    	meta: "validate"


Hope this is helpful to someone. Someday-maybe I’ll post an update when I clean it all up. A next step could be to handle the entire form onsubmit, but cake already does that with the model validation that we just added.



jQuery –
jQuery Form Validation and meta plugin: