Stream of Ry

Yet Another Geek In The World

CakePHP and AJAX: Inline Editing

12 comments

** Warning: Heavy Webdev Jargon Post — Javascript, PHP, Object-oriented concepts **

So, I spent my entire weekend trying to wrap my head around how CakePHP does things, but I spent more time trying to figure out how to make different AJAX methods to work with it.

Well, for starters, CakePHP is an rapid development MVC framework for PHP. It’s similar with RoR and Groovy and Grails. It implements ORM… and a lot more. ( If you have trouble with some of the jargon they have on the site, you can ask me here and I’ll try explaining them. )

Here’s my supposed laundry list of AJAX stuff to try:

  • Inline editing
  • Drag and Drop
  • Dynamic updating of selects
  • Quick saving

So far, I’ve finished… 1 of 4. X3

Inline Editing

Guides: The 15-minute blog, Cakebaker, CakePHP.bee.pl

I was initially following the 15 minute blog tutorial just to reinforce my *baking* skills, and nothing beats going through the basics again. I stopped at around 10.1.13 Routes and then proceeded with Cakebaker’s guide. Though, Cakebaker’s guide is complete by itself (he’s got code for the Model, View and Controller), it is still pretty important that you let the MVC paradigm sink in first before you follow any other guide that does not deal with the basics. Oddly enough, I can’t get it to work. I’m copy-pasting his code onto mine and making the appropriate changes but still, doesn’t work. So, after reading through the comments, I followed a link to a JQuery-based AJAX helper for CakePHP. (The default is for prototype and script.aculo.)

The said helper had a built-in method for inline editors, so I said, hey, what the heck. Might as well try. The examples were great as it showed you that it does what you need.. but eventually you’ll realize there’s something missing. Yep, the code for the controller. So, combining the Cakebaker’s guide and the documentation for this helper, I managed to (finally) make inline editing work. For this example, we’re using Cakebaker’s model and controller (Post) but we’re using the syntax of the helper for the view. I’ve also modified Cakebaker’s controller method to work with the helper.

Here are the relevant files:
In app/app_controller.php: [1]

<?php
 
class AppController extends Controller {
    public $helpers = array('Html','Form','Javascript','Ajax');
    public $components = array('RequestHandler');
}
 
?>

In app/views/posts/index.ctp: [2]

<?php foreach ($posts as $post): ?>
<div class="post" id="div_<?php echo $post['Post']['id']; ?>"><?php echo $post['Post']['title']; ?></div>
<?php echo $ajax->editor(
    "div_".$post['Post']['id'],
    array(
        'controller' => 'Posts',
        'action' => 'updateTitle'
    ),
    array(
        'submit' => 'OK',
        'style' => 'inherit',
        'submitdata' => array ('id' => $post['Post']['id']),
        'tooltip' => 'Click to edit',
    )
);?>
<?php endforeach; ?>

In app/controllers/posts_controller.php: [3]

public function index() 
{
    $this->set('posts', $this->Post->find('all'));
}
 
public function updateTitle()
{
    /*
        echo $this->params['form']['id'];
        echo $this->params['form']['value'];
    */
    if ($this->RequestHandler->isAjax())
    {
        App::import('Core', 'sanitize');
        $title = Sanitize::clean($this->params['form']['value']);
 
        $this->Post->id = $this->params['form']['id'];;
        $this->Post->saveField('title', $title);
 
        Configure::write('debug', 0);
 
        $this->set('posttitle', $title);
    }
}

In app/views/forms/update_title.ctp: [4]

<?php echo $posttitle;?>

Now for the explainin’:
[1] I’ve put the helpers and components array in the app_controller.php so that I don’t need to update *every single one* of my controllers. This is more of a convenience and I’m sure, on production level sites, this is not advisable as you will incur overhead for loading extra stuff that you won’t need anyway.

[2] This is taken from the documentation of the AJAX helper. Basically, it iterates over all of the posts and generates both a display div and an editor for each post title.

[3] The index function is there in order for the index view to work. Just gets all of the posts.
[3] If you look closely, updateTitle looks *almost* the same as the one at Cakebaker’s but I’ve changed how I get the data. Apparently, $this->data does not contain anytihng. I’ve tried echoing it, and even the word Array doesn’t show up. So, instead, I turned to $this->params['form'] to get all of the data passed on by any form in the page. The RequestHandler is there to check if the Request is an Ajax request. The reason for this is that we need to turn debugging levels to 0 (Configure::write) since we’re basically passing on a view and if debug levels weren’t set to 0, it passes on the whole debug messages back (including SQL stats). >_<

[4] The view to be rendered to replace the updated data in the editor div.

Note: I’ve read this article that utilizes the beforeFilter behavior in the AppController to detect if the request is an AJAX request and then changes debug levels appropriately. This could potentially save a lot of time but could incur overhead, I s’pose.

While this took me literally hours to figure it, the enlightenment I got makes it worth it. :) I’ll be working on Quick Save, Dynamic Selects and Drag and Drop, in that order in the next few days and I’ll make sure I will put up any learnings I get here. This makes for a very convenient documentation place. X3
*Naku, may mga projects pa ako at ito ang inaatupag ko. (doh)*

Written by rystraum

April 4th, 2010 at 6:40 am

12 Responses to 'CakePHP and AJAX: Inline Editing'

Subscribe to comments with RSS or TrackBack to 'CakePHP and AJAX: Inline Editing'.

  1. Try using syntax highlighter for your code. :D

    Jeune

    4 Apr 10 at 10:42

    Reply

  2. @Jeune: That took me a while to fix up. But it should be okay now. I was wrestling with escaping html characters for some 5 or so updates. X3

    rystraum

    4 Apr 10 at 16:20

    Reply

  3. What problem did you encounter with the code from my blog? You simply mention it didn’t work…

    • If I remember correctly, the changes aren’t being saved to the database. Now that I think about it, I should have checked with the javascript if I’m calling the proper class/method. I may update on this, but since I started working in Code Igniter again, it could take a little more while before I get to try it out again. :)

      rystraum

      8 Apr 10 at 02:31

      Reply

  4. i have a problem with retrieving data from the DB…

    Here’s my select query:

    $companies = $this->Company->find( 'all' );	
    $this->set( 'companies', $companies );

    And here’s the view:

    foreach($companies AS $keys => $values){
    echo $values['Company']['address'];
    }

    Edit: Enclosed code in pre tags

    new

    26 Jul 10 at 23:46

    Reply

    • Try replacing the view from your:

      foreach($companies as $keys => $values){
      echo $values['Company']['address'];
      }

      to:

      foreach ($companies as $company){
      echo $company['Company']['address'];
      }

      Your problem could be related to your foreach operating over the keys and values instead of just for each instance in the array.

      Then again, your question is a bit too broad so I don’t know if *this* is the cause of your problem.

      I haven’t been doing PHP (let alone Cake) for quite a while so pardon me if I don’t remember it much.

      rystraum

      27 Jul 10 at 02:53

      Reply

  5. how is validation error spewed ?

    Ay

    4 Mar 11 at 03:57

    Reply

  6. Thanks for this it really got me off the ground with inline editing and cakephp.

    Simon

    9 Apr 11 at 04:06

    Reply

  7. I think u have wrong path to your view:

    In app/views/forms/update_title.ctp: [4]

    it should be:

    In app/views/posts/update_title.ctp: [4]

    MJ

    10 Apr 11 at 13:57

    Reply

  8. The editor box does not appear. Can you help me? Thanks.

    j22bad

    15 Apr 11 at 02:19

    Reply

  9. Please disregard my previous question. I did get the editor box to work. However, when I update the editing field (click ok), the entire view of the submitdata is loaded into div. It is somehow never reaching the desired action of the controller. Newbie, can you help? Thanks!

    j22bad

    15 Apr 11 at 19:31

    Reply

Leave a Reply