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.
<?php
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.
if(is_array($this->data['User'])){
// $this->cleanUpFields();
// Validate the User, if it's ok, show no errors. If not ok, show errors
$this->User->create($this->data);
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');?>
<fieldset>
<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');?>
</fieldset>
</div>
<?php //extra javascript for this view
echo $javascript->codeBlock('
$(document).ready(function() {
$("#UserIndexForm").validate({
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.
Cheers!
References
jQuery – http://docs.jquery.com/Plugins/Validation
jQuery Form Validation and meta plugin: http://bassistance.de/jquery-plugins/jquery-plugin-validation/
Recent Comments