Ajax saving with jQuery and Kohana
Yesterday a post dealing with ajax saving with jQuery and CakePHP popped up on my rss-feeds. The same thing can of course be done with Kohana and jQuery and the approach is quite similar.
Similar conditions to the last ajax post apply. All examples will be based on this previous tutorial so you might want to read it.
Anyway, this tutorial requires basic knowledge of ORM and the Template_Controller. Furthermore, if you use Kohana 2.1 you should download the request helper.
We’ll continue with the students table of last time.
-- -- Table structure for table `students`, dorm_id will not be used today -- CREATE TABLE IF NOT EXISTS `students` ( `id` mediumint(9) NOT NULL AUTO_INCREMENT, `name` varchar(255) collate utf8_unicode_ci NOT NULL, `dorm_id` mediumint(9) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ; INSERT INTO `students` (`id`, `name`, `dorm_id`) VALUES (1, 'student 1', 1), (2, 'student 2', 1);
And the model again is:
//models/student.php class Student_Model extends ORM{ }
The template is also the same, only one difference
//views/template.php <html> <head> <title>Kohana jQuery Ajax tutorial</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script> <script type="text/javascript" src="http://example.com/assets/js/jquery.form.js"></script> <style type='text/css' media='all'> #flash-message{ width:300px; height:30px; padding-top:15px; text-align:center; margin-bottom:20px; font-weight: Bolder; } .flash-error{ color:Red; background-color: #f6c0c9; border:1px solid #d32f4a; } .flash-notify{ color:Blue; background-color: #bfbaf5; border:1px solid #4237d8; }</style> <? echo isset($head) ? $head : '' ?> </head> <body> <?= $content ?> </body> </html>
Again, you can see I have a variable $head which is where all the jQuery code is going to be. The difference lies in the form plugin. Make sure you put it in the right place. I also added a little styling for the flash messages. Will be covered later.
Anyway, on to the controller:
//controllers/student.php class Student_Controller extends Template_Controller { public function index() { $this->template->content=new View('student/index'); $this->template->content->students=ORM::factory('student')->find_all(); } }
The view for /student/index is the same as last time only now has a edit link instead of delete
//views/student/index.php <table id="students"><?php foreach ($students as $student) { echo "<tr><td>".$student->id."</td><td>".$student->name."</td><td>".html::anchor('student/edit/'.$student->id,'Edit')."</td></tr>"; } ?> </table>
This means we’ll need an edit method in our controller.
public function edit($id) { //$this->template->head=new View('student/ajax_save'); //uncomment later on $student=ORM::factory('student',(int) $id); $form=new Forge(url::current(), 'Edit', 'POST'); $form->input('name')->value($student->name); $form->submit('submit'); if($form->validate()) { $student->name=$form->name->value; //get value of form element $student->save(); url::redirect('student/index'); } else { $this->template->content=$form; } }
When you click on an edit link in the index method you’ll see a form to change the name of the student. I created the form with Forge for ease but any form will do. This is all fully functional without javascript.
Next step is adding the ajax. Like last time we’ll fill the $head variable in the template. Uncomment the first line in the ‘edit’ method and create a view ‘views/student/ajax_save.php’
<script type="text/javascript"> //views/student/ajax_save.php $(document).ready(function() { //attach onSubmit to the form $('#edit_form').submit(function(){ //When submitted do an ajaxSubmit $(this).ajaxSubmit({ dataType: 'json', success: function(data, responseCode) { //Show flash message as first element after body jQuery('<div id="flash-message" class="flash-'+data.flash_class+'">').hide().html(data.text).prependTo('body').fadeIn(); //Show for 5 seconds setTimeout(function(){ $('#flash_message').fadeOut(); }, 5000); } }); //return false to prevent normal submit return false; }) } ); </script>
You’ll see it resembles the js in the Cakephp tutorial but there are some differences. We replace the functionality of the submit button with an ajax submit instead of adding another button. Also we use json to return a message and a class. The code will show a div for a couple of seconds when submitting the form through ajax, form will either be red or blue depending on whether the an error was given or not.
Let’s look at the new controller code.
public function edit($id) { $student=ORM::factory('student',(int) $id); $form=new Forge(url::current(), 'Edit', 'POST'); $form->set_attr('id','edit_form'); $form->input('name')->value($student->name); $form->submit('submit'); if(request::is_ajax()) { if($form->validate()) { $student->name=$form->name->value; //get value of element $student->save(); echo json_encode(array('flash_class'=>'flash-notify','text'=>'Saved succesfully')); } else { $errors=$form->errors(); echo json_encode(array('flash_class'=>'flash-error','text'=>'Error during saving') ); } $this->auto_render=false; //Disable the auto renderer, we don't want a layout in our ajax response return; } $this->template->head=new View('student/ajax_save'); if($form->validate()) { $student->name=$form->name->value; $student->save(); url::redirect('student/index'); } else { $this->template->content=$form; } }
You can see that we return a json object on success and failure. The json object contains the class we want to attach to the flash message, and the message itself.
You see that using the power of jQuery this stuff becomes incredibly easy. Again, we have accomplished code that will work with or without javascript.
I hope this was clear. I kept the code a little more verbose to maintain clarity.
July 18th, 2008 at 5:41 am
[...] bookmarks tagged ajax Ajax saving with jQuery and Kohana saved by 3 others gli0444 bookmarked on 07/17/08 | [...]
July 31st, 2008 at 3:27 pm
Shouldn’t this:
$student=ORM::factory(’student’,(int) $id);
Be before:
if(request::is_ajax())
As far as I can see php would throw some kind of ‘calling method on non object’ error.
Otherwise it seems like a nice introduction to ajax
July 31st, 2008 at 10:00 pm
You’re right, missed that
Thx, I’ll fix it.
August 3rd, 2008 at 2:30 pm
$(’#edit-form’).submit(function(){
should be
$(’#edit_form’).submit(function(){
August 3rd, 2008 at 7:24 pm
Fixed! Thanks for the close read
August 29th, 2008 at 7:41 pm
When I click on a edit link a error message shown stated that:
Fatal error: Class ‘Form_Input’ not found in C:\xampp\htdocs\Kohana\system\libraries\Forge.php on line 93
I have downloaded the Forge class and kept it in Library folder. So why this is happening? Would someone help me?
August 30th, 2008 at 9:12 am
I think I have overcome from the first problem. Now I am facing another problem when I click on the edit link. An error message is displayed stated that:
//views/template.php
Fatal error: Method Forge::__toString() must not throw an exception in C:\xampp\htdocs\Kohana\application\views\template.php on line 32
How can I overcome this situation?
August 31st, 2008 at 9:00 am
Yes
Finally I have made it!
This tutorial is awesome!!!;)