1. #1
    Sencha User
    Join Date
    Apr 2012
    Posts
    7
    Vote Rating
    0
    shethvoss is on a distinguished road

      0  

    Default 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);
        },

  2. #2
    Sencha - Community Support Team
    Join Date
    Jan 2012
    Posts
    1,376
    Vote Rating
    113
    vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all

      0  

    Default


    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
    Code:
    {"id":0, "f1": "F1",...}
    server side script should return a json data like this to update client side data in store
    Code:
    {
        "success": true,
        "data": [{"id":<newly created id>, "f1": "F1", ...}]
    }

  3. #3
    Sencha User
    Join Date
    Apr 2012
    Posts
    7
    Vote Rating
    0
    shethvoss is on a distinguished road

      0  

    Default


    Thanks so much! I changed the server API and can see that POST returns JSON data exactly like you describe:

    Code:
    {    "success":true,    
        "data":[ { "id":37,  "name":"default", ... }]
    }
    But I think i'm still making a mistake calling the code from Ext JS. Is this supposed to be right?

    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
        },

  4. #4
    Sencha - Community Support Team
    Join Date
    Jan 2012
    Posts
    1,376
    Vote Rating
    113
    vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all

      0  

    Default


    Quote Originally Posted by shethvoss View Post
    Thanks so much! I changed the server API and can see that POST returns JSON data exactly like you describe:

    Code:
    {    "success":true,    
        "data":[ { "id":37,  "name":"default", ... }]
    }
    But I think i'm still making a mistake calling the code from Ext JS. Is this supposed to be right?

    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
        },
    Because the creating request is asynchronous, you have to wait for the whole process of request completes. If you want to check the id of newly created record, you should wait for 'write' event on the store.

  5. #5
    Sencha User
    Join Date
    Apr 2012
    Posts
    7
    Vote Rating
    0
    shethvoss is on a distinguished road

      0  

    Default 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'
            }
        } ,

  6. #6
    Sencha - Community Support Team
    Join Date
    Jan 2012
    Posts
    1,376
    Vote Rating
    113
    vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all

      0  

    Default


    Quote Originally Posted by shethvoss View Post
    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.
    Yes, that's right.

    Quote Originally Posted by shethvoss View Post
    That set, when the 'write' method gets called, the id is properly assigned within the grid.
    I am not sure to understand this. Could you explain it more clearly?

  7. #7
    Ext JS Premium Member
    Join Date
    Apr 2010
    Location
    Montréal, Canada
    Posts
    221
    Vote Rating
    5
    Christiand is on a distinguished road

      0  

    Default


    Quote Originally Posted by vietits View Post
    I am not sure to understand this. Could you explain it more clearly?
    Code:
    var store = Ext.create(Ext.data.Store,{
        ...
        listeners: {
            update: function(store, model operation){
                 // do your ID checking here
            }
        }
    });
    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).

    I mentioned "update" listeners. There are many listener available. Check out what they do, play with them until you find what you need.

  8. #8
    Sencha - Community Support Team
    Join Date
    Jan 2012
    Posts
    1,376
    Vote Rating
    113
    vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all

      0  

    Default


    Ah, yes. That's right.

Thread Participants: 2

Tags for this Thread