-
27 Apr 2012 6:43 AM #1
Create new record in store, and sync id with that assigned by remote RESTful service?
Create new record in store, and sync id with that assigned by remote RESTful service?
Newbie to ExtJS. So far I can successfully retrieve a list of existing records from a remote RESTful API (i.e. GET: http://localhost/api/elems/) into a Store, display those records in an GridPanel, display them in a popup form, save those records back, and see the records updated both in my local app as well as the remote database (i.e. PUT: http://localhost/api/elems/{id}) . All this following the ExtJS tutorial (but changed Users to Elems). So far very easy.
Now I'd like to add the ability to create and edit a "New element". I added a button "New element" in a tbar on top of the "MyApp.view.List" widget, which calls onNewElem() below. That creates a new record with default values for everything (id=0) ,and adds it to the store (MyApp.store.Elems). Since the store has "autoSync: true", that immediately appears on the server (POST: http://localhost/api/elems), and peeking inside MySQL I can see the record has been created and assigned a new valid id (e.g. id=17)
But the local record still has an id=0. When I try to edit and update the record, it fails, sending results to an API that doesn't exit (PUT: http://localhost/api/elems/" rather than PUT: http://localhost/api/elems/17).
If I refresh the page, the app retrieves the correct id (e.g. id=17) and I can edit/update it fine. But if I create a new record, the same issue appears.
Hacking, I tried calling this.getElemsStore().sync() but that doesn't seem to help, it simply calls POST twice, creating two copies of the new record (id=17, id=18) on the remote database, and worse, only the first new record appears in the local list.
What's the right way to create a new record in Ext JS 4?
Thanks!
Pieter
Code:Ext.define('MyApp.controller.Elems', { extend: 'Ext.app.Controller', stores: ['Elems'], models: ['Elem'], .... onNewElem: function() { var rec = Ext.create('MyApp.model.Elem', {name: 'default'}); var s = this.getElemsStore(); console.log("Before adding: id="+rec.get('id')); // id=0, as expected s.add(rec); // in MySQL, the record has been added and assigned id=17 console.log("After adding: id ="+rec.get('id')); // id=0, not expected // s.sync(); // Just creates a second post, but local id still is 0 }, editElem: function(grid, record) { console.log('Double clicked on '+record.get('name')+ " id="+record.get('id')); var view = Ext.widget('elemEdit'); // alias of MyApp.view.elem.Edit view.down('form').loadRecord(record); },
-
27 Apr 2012 5:49 PM #2
What does your server side script return after getting creating request from client and creating a new record in your database? It seems that your script does not return the record with new id to update the client side.
With creating request data
server side script should return a json data like this to update client side data in storeCode:{"id":0, "f1": "F1",...}
Code:{ "success": true, "data": [{"id":<newly created id>, "f1": "F1", ...}] }
-
28 Apr 2012 6:54 PM #3
Thanks so much! I changed the server API and can see that POST returns JSON data exactly like you describe:
But I think i'm still making a mistake calling the code from Ext JS. Is this supposed to be right?Code:{ "success":true, "data":[ { "id":37, "name":"default", ... }] }
Code:onNewElem: function() { var rec = Ext.create('Protobi.model.Elem', {name: 'default'});; console.log("Before adding: id="+rec.get('id')); // 0, good var recs = this.getElemsStore().add(rec); console.log("rec.id == "+rec.get('id')); // still says 0 console.log("recs[0].id == "+recs[0].get('id')); // recs.length=1, recs[0].id is also 0 },
-
29 Apr 2012 5:04 AM #4
-
30 Apr 2012 4:56 AM #5
Thanks
Thanks
Perfect! The last little thing, recording here just for completeness, was making sure that the 'root' property in the proxy was set to the same as the 'data' property in the returning Json. That set, when the 'write' method gets called, the id is properly assigned within the grid.
Code:Ext.define('MyApp.store.Elems', { extend: 'Ext.data.Store', model: 'MyApp.model.Elem', autoLoad: true, autoSync: true, proxy: { type: 'rest', url: 'http://localhost:8080/services/api/elems', reader: { type: 'json', root: 'data', successProperty: 'success' }, writer: { type: 'json' } } ,
-
30 Apr 2012 5:31 AM #6
-
30 Apr 2012 8:12 AM #7
When you create a record in a store configured for remote operations, you do not need to set the ID. The record will stay phantom until it gets the successful reply from the server, then apply the result to the record and remove the phantom flag (this is all done automatically). It makes sense, because anyone with such configuration wants to have the ID generated on the server side (or most of the time).Code:var store = Ext.create(Ext.data.Store,{ ... listeners: { update: function(store, model operation){ // do your ID checking here } } });
I mentioned "update" listeners. There are many listener available. Check out what they do, play with them until you find what you need.
-
30 Apr 2012 3:12 PM #8
Ah, yes. That's right.


Reply With Quote
