Recently, while working with a model and proxy in ExtJS 4, I ran into the issue where the model’s proxy would call the ‘create’ action instead of ‘update’ when saving changes to an existing record. Here’s the sample model and store we’ll be using to duplicate the problem:
Ext.Loader.setConfig({ // Set up auto-loading
enabled: true,
paths: {
Ext: 'extjs/src'
}
});
Ext.define('User', { // The store
alias: 'widget.userModel',
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'name',
type: 'string'
}, {
name: 'dob',
type: 'date',
dateFormat: 'Y-m-d'
}],
proxy: {
type: 'ajax',
api: {
create: 'myBackend.php?action=create', // Called when saving new records
read: 'data/users.json', // Called when reading existing records
update: 'myBackend.php?action=update', // Called when updating existing records
destroy: 'myBackend.php?action=destroy' // Called when deleting existing records
},
reader: {
type: 'json', // We expect the server to give us a JSON string as a response
root: 'users'
}
}
})
Ext.define('Users', {
extend: 'Ext.data.Store',
alias: 'widget.userStore',
model: 'User',
autoLoad: false,
autoSync: true
});</pre>
This is a pretty straightforward example. We have a 'User' model with the following fields: id, name and dob (date of birth) and a store that is tied to that model. Let's load up one of those user objects from the database and try to change the title:
<pre escaped="true" lang="javascript" line="1">Ext.onReady(function() {
Ext.widget('userModel').self.load(1, {
success: function(record, operation) {
record.data.name = 'Joe Smith';
}
})
})
Now let’s try saving our changes and take a peek at the AJAX request sent to the server (via Chrome’s JavaScript tools console):
Console Output:
record.save();
url: http://www.dev.levihackwith.com/dnd_dev/myBackend.php?action=create&_dc=1309112727215
Query String Parameters:
action:create
...
1
As you can a see, our proxy attempted to create the record via the model proxy's 'create' api command instead of update it using the 'update' command. Why is this? Well, let's take a closer look at the record that was returned to us when we called the model's load method:
<a href="http://www.levihackwith.com/wp-content/uploads/2011/06/ScreenClip.png"><img class="size-full wp-image-72" title="Loaded User Model" src="http://www.levihackwith.com/wp-content/uploads/2011/06/ScreenClip.png" alt="User model returned when save() was called" width="513" height="204" /></a>
See the model's "phantom" property? That's been set to true. Let's learn a little more about this property via the API documentation (emphasis mine):
<blockquote>Phantom: Boolean
True when the record does not yet exist in the server-side database (see setDirty). <strong>Any record which has a real database pk [primary key] set as its id property is NOT a phantom</strong> -- it's real.</blockquote>
Now, what does that mean, exactly? Well, when you are setting up a model, one of the properties you can set is the idProperty property. This specifies which field in the model serves as the unique identifier for that record when it's sent and received from the server. Now let's take another look at the response from the server:
1
{
'success': true,
'users':[{
'id': '',
'name': 'John Smith',
'dob': '1980-06-12'
}]
}
See how the ID field is blank? Because it’s blank, Ext assumes that it’s not been saved to the database yet and sets the Phantom property to true. Once we adjust our backend code to set the value of the field that acts as the idProperty (in this case, “id”), Ext recognizes the record as coming from the server and sets Phantom to false:
So, next time your proxy starts misbehaving, double check your server responses and model configuration and make sure you’re returning a fully-populated object. Happy coding!
ExtJS, Lessons Learned




Thanks! Solve my problem.
Thanks for this post. I’ve spent 2 days Googling, and a forum post at Sencha before I found your page. It’s the solution to my problem. I added the idProperty into my model and my REST proxy started working as expected.
Great post, thank you!
Now I’ve run into trouble with my store is calling update instead of create when I add new node to a TreePanel. Can anyone suggest what can be reason of that?
Thanks a lot.. You have saved the day !
[...] ExtJS 4: Proxy Calling ‘Create’ Instead of ‘Update’ When Saving Record. [...]
Thank you so much for this post. I was trying to solve this riddle for a whole day. I think I would have never figured it out on my own — I wasn’t even using the idProperty in my script.
Thank a lot! I was banging my head on the wall. It makes sense though, how is the update api going to work without an id to reference?
Thanks a lot, it really help a lot.
terrific post. this helped me ferret out a nasty bug, and come to a deeper understanding of what’s going on behind the scenes with the proxy’s CRUD calls.
thanks!
Another thing: found about the ‘encode’ config option of Ext.data.writer.Json that puts the post data in the url. Thus you can access it in the backend with $_REQUEST, without the need for ‘raw data’ manipulation.
Awesome! I’m glad you were able to get everything working.
Ok, solved this. Put proxy in store’s definition and then, on grid edit put ‘this.store.sync()’. Everything started to work. I updated the JSFiddle code. Go check it out!
Oh, and thanks for the editing example, i will put it to good use!
I need to return the completed model object along with the success message from the server’s JSON output, or else ‘record = operation.getRecords()[0];’ will trigger ‘Uncaught TypeError: Cannot read property ‘data’ of undefined’
I wasn’t able to spot anything that used operation.getRecords()[0]. I’d suggest checking out Sencha’s grid editing example. Maybe it’ll help. http://dev.sencha.com/deploy/ext-4.0.0/examples/grid/cell-editing.html
link to updated JSFiddle
http://jsfiddle.net/rikkman/fQEkW/
Ok, now the problem is ‘Uncaught TypeError: Cannot read property ‘data’ of undefined’. Everything else is fine: save works but this ‘record = operation.getRecords()[0];’ remains undefined.
There you go
http://jsfiddle.net/rikkman/fQEkW/1/
this code sends POST action create/update on grid edit, with request payload in raw data
Will do, ’cause this thing is driving me loony!
And i need all the help i can find
Sounds like a plan. If there’s other areas of ExtJS 4 you want me to cover, let me know.
Moved the proxy definition to model and now the issue is that i can only get the request payload on the php server side with the $GLOBALS['HTTP_RAW_POST_DATA']. Have to do some trickery to insert into mongodb…
Ah! Yes! I need to write about the whole “raw data” issue sometime. You should post your code to JS Fiddle and post a link here so others can follow along with what you did.
Ok, maybe the server error isnt the problem, because before that i get ‘Uncaught TypeError: Cannot call method ‘indexOf’ of undefined’ on saving from editing a grid ‘e.record.save();’
URL: http://localhost/myApp/app/resources_crud.php?action=update&_dc=1309355122800
Método: POST
Estado: 500 Internal Server Error
Duração: 220 ms
Detalhes do pedido
POST /myApp/app/resources_crud.php?action=update&_dc=1309355122800 HTTP/1.1
User-Agent: Opera/9.80 (Windows NT 5.1; U; pt) Presto/2.9.168 Version/11.50
Host: localhost
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: pt-PT,pt;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate
Referer: http://localhost/myApp/resources.php
Connection: Keep-Alive
Content-Length: 152
Content-Type: application/json
X-Requested-With: XMLHttpRequest
Content-Transfer-Encoding: binary
Detalhes da resposta
HTTP/1.1 500 Internal Server Error
Server: nginx/1.0.4
Date: Wed, 29 Jun 2011 13:45:23 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.3.6
When i try this code my server complaints about POST method status 500 Internal Server Error. Maybe because the api update url is composed with ‘?action=update’, like a normal GET request?
Thanks,
Ricardo
Hmmm. If you’re getting an internal server error, it’s most likely something with the backend code. The URL’s I used were completely made up and just for example. I’d check the AJAX response from the server and see what’s getting sent and received. If you’re still having trouble, please let me know.
By the way, it looks like you’ve not tagged this, as it doesn’t show up under the ‘extjs’ tag.
Andy
Good post – thanks for sharing that. I’m only just beginning to move from ExtJS3 to 4, so it’s good to see some useful blog posts to make the path a little easier.
Regards,
Andy