CakePHP and EXTJS Forms
UPDATE NOTE - I removed a trailing comma on line 38 of myForm.js. It was causing IE problems.
UPDATE NOTE 2 - I changed the way I named the variables in myForm.js so that they are more cake-friendly. That makes the controller work like a regular application (if $data isn’t empty, save . . .). I got this idea from cakebaker’s new tutorial using jquery (http://cakebaker.42dh.com/2008/02/24/edit-in-place-with-jquery-and-cakephp/)
OK, several people have asked how to do this, so here’s how it works. EXTJS forms use ajax by default. You can make them submit like regular forms (see here: http://extjs.com/forum/showthread.php?t=8397&highlight=cancel+form+submit), but I’m going to use ajax/json today. I’m going to create a form that will add to my users database/datagrid from my last tutorial. You need to at least read this one first and setup the basics (include EXT, the host variable, etc).
NOTE - There may be an easier way to do this, but this is the best I’ve been able to come up with.
First, we’ll look at the controller. You need 2 (yes, two) controller functions to make this work. First, we’ll make a function called add:
1 2 3 4 | function add() { //blank controller function } |
Basically, this function exists for one reason only - it calls it’s view, which calls our javascript file (myForm.js, in this case).
The view is add.ctp and looks like this:
1 2 | <div id="user-form"></div> <?php echo $javascript->link('myForm'); ?> |
It creates a div to hold our form, and it calls our js file. Now for the second controller function. I named it (creatively enough) add2. Here’s the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | function add2() { Configure::write('debug', '0'); //turn debugging off; debugging breaks ajax $this->layout = 'Ajax'; //set the layout to Ajax so the ajax doesn't break //Cake does everything automagically through $this->data //Since we aren't using cake's automagic, we have to fake things a little //When a form is submitted, we are going to take the data submitted ($this->params['form']['username'] //and assign it to $this->data['User']['username'] to make it fit with cake's automagic. //Otherwise, we can't use cake's save functions //Part of UPDATE2 - we don't need to do this anymore; it's taken care of in myForm.js //$this->data['User']['username'] = $this->params['form']['username']; //$this->data['User']['fullname'] = $this->params['form']['fullname']; //This is just like regular cake except for the set statements if (!empty($this->data)) { $this->User->create(); if ($this->User->save($this->data)) { $this->set('success', '{success:true}'); //this is a json statement. EXT forms need this to know if things worked } else { $this->set('success', '{success:false}'); //EXT forms need this to know if something went wrong } } } |
OK, the comments should explain things there. The view is add2.ctp:
1 | <?php echo $success; ?> |
All this does is print the json return string we set in our controller. EXT forms need this to know if things worked or not. Since we are calling add2 through ajax, this page won’t be called directly, and the success statement won’t be printed to the screen. It will show up in firebug, though.
OK, now for the javascript (myForm.js - save it in /webroot/js).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | Ext.onReady(function(){ Ext.QuickTips.init(); //make a new form var form_user = new Ext.form.FormPanel({ frame: true, title: 'Add User', bodyStyle: 'padding: 5px 5px 0', width: 350, labelWidth: 75, defaults: {width: 230}, //this is the default field width defaultType: 'textfield', //this is the default field type. You don't have to set this, but if not, you'll have to set it for each item items: [{ fieldLabel: 'User Name', //label text name: 'data[User][username]', //field name for submit purposes allowBlank: false //simple validation }, { fieldLabel: 'Full Name', name: 'data[User][fullname]', allowBlank: false }], buttons: [{ text: 'Save', //text for submit button type: 'submit', //type for button handler: function() { //what happens when you click the button? form_user.form.submit({ url: 'http://'+host+'/ext/users/add2', success: function() { Ext.MessageBox.alert('Message', 'It worked!', function(){window.location.href = 'http://'+host+'/ext/users/'}); }, failure: function() { Ext.MessageBox.alert('Message', 'Save failed!'); } }); } }, { text: 'Cancel', handler: function() { form_user.form.reset(); } }] }); form_user.render('user-form'); }) |
OK, here’s what’s going on. Line 3 creates a new formPanel. The next several lines set different formPanel options. Line 14 starts defining our form fields. Line 24 defines our buttons. Line 27 defines the handler for our submit button. That’s how the form submits. NOTE - I’m using the host definition from my last tutorial. Success on line 30 is determined by the return value from add2 - success (true) or failure (false). If success is true, a message pops up to tell you ‘It worked!’, then it redirects to the datagrid from my last tutorial. If success is false, a message pops up to tell you the save failed. Cancel just resets the form.
There, I did it before going home for the weekend! Yeah! I hope this helps some people.
hydra12