1. #1
    Ext User
    Join Date
    May 2009
    Posts
    5
    Vote Rating
    0
    curvatique is on a distinguished road

      0  

    Default [3.0 RC1.1] DirectStore.api.save request params Question

    [3.0 RC1.1] DirectStore.api.save request params Question


    Hello All,

    I seem to have some trouble understanding the way DirectStore.Api.save maps its request data. Looking at firefox when some record in the store gets saved the request takes on the following format (json):

    Code:
    {
      "action":"employee",
      "method":"update",
      "data":[
         "115",
         {"name":"Employee 121sss","id":"115"}],"type":"rpc",
      "tid":3
    }
    Is the data property intentionally an array with both scalars ánd objects? Why does it put the ID separate from the rest of the data (even with API methods that have a len of 1) - in other words, why supply two sets of parameters to the server when there's only one parameter that is expected by the server?

    Then if this is intentionally then how to expect the router (and/or the client) to know to go to the second set of data to get all of the neccesary parameters

    the following code will reproduce the scenario:
    HTML Code:
    Ext.onReady(function(){
    
        Ext.Direct.addProvider(Ext.app.EXT_API);
    
        //reader
        var reader = new Ext.data.JsonReader({
            totalProperty: 'total',
            successProperty: 'success',
            idProperty: 'id',
            root: 'data'
        }, [
            { name: 'id', type: 'int'},
            { name: 'name',type: 'string'},
            { name: 'email', type: 'string' },
            { name: 'salary', type: 'float'},
            { name: 'active', type: 'boolean'},
            { name: 'created_at', type: 'date', dateFormat: 'Y-m-d H:i:s'}
        ]);
    
        //writer
        var writer = new Ext.data.JsonWriter({
            returnJson: false,
            writeAllFields: false
        })
    
        //Direct Store
        var store = new Ext.data.DirectStore({
            storeId:'employee-store',
            api: {
              load: employee.load,
              save: employee.update
            },
            sortInfo: {
                field: 'created_at',
                direction: 'DESC'
            },
            remoteSort: true,
            paramsAsHash: true,
            autoLoad : true,
            reader: reader,
            writer: writer
        });
    
        //grid
        var grid = new Ext.grid.EditorGridPanel({
            store: store,
            width: 600,
            region:'center',
            margins: '0 5 5 5',
            autoExpandColumn: 'name',
            loadMask: true,
            columns: [{
                id: 'name',
                header: 'name',
                dataIndex: 'name',
                width: 220,
                sortable: true,
                editor: {
                    xtype: 'textfield',
                    allowBlank: false
                }
            },{
                header: 'Email',
                dataIndex: 'email',
                width: 150,
                sortable: true,
                editor: {
                    xtype: 'textfield',
                    allowBlank: false,
                    vtype: 'email'
                }
            },{
                xtype: 'datecolumn',
                header: 'Start Date',
                dataIndex: 'created_at',
                format: 'm/d/Y',
                width: 100,
                sortable: true,
                groupRenderer: Ext.util.Format.dateRenderer('M y'),
                editor: {
                    xtype: 'datefield',
                    allowBlank: false,
                    minValue: '01/01/2006',
                    minText: 'Can\'t have a start date before the company existed!',
                    maxValue: (new Date()).format('m/d/Y')
                }
            },{
                xtype: 'numbercolumn',
                header: 'Salary',
                dataIndex: 'salary',
                format: '$0,0.00',
                width: 100,
                sortable: true,
                editor: {
                    xtype: 'numberfield',
                    allowBlank: false,
                    minValue: 1,
                    maxValue: 150000
                }
            },{
                xtype: 'booleancolumn',
                header: 'Active',
                dataIndex: 'active',
                align: 'center',
                width: 50,
                trueText: 'Yes',
                falseText: 'No',
                editor: {
                    xtype: 'checkbox'
                }
            }],
            bbar: new Ext.PagingToolbar({
                pageSize: 25,
                store: store,
                displayInfo: true,
                displayMsg: 'Displaying topics {0} - {1} of {2}',
                emptyMsg: "No topics to display"
            })
        });
    
        //Layout
        var layout = new Ext.Panel({
            title: 'Employees',
            layout: 'border',
            layoutConfig: {
                columns: 1
            },
            width:600,
            height: 600,
            items: [grid]
        });
        layout.render(Ext.getBody());
    
    });
    Kind Regards

    Ad

  2. #2
    Ext JS Premium Member christocracy's Avatar
    Join Date
    Oct 2006
    Location
    Montreal
    Posts
    381
    Vote Rating
    0
    christocracy is on a distinguished road

      0  

    Default


    Hi, yes this one has been on the back of my mind. I'll ponder it a bit.
    /**
    * @author Chris Scott
    * @business www.transistorsoft.com
    * @rate $150USD / hr; training $500USD / day / developer (5 dev min)
    *
    * @SenchaDevs http://senchadevs.com/developers/transistor-software
    * @twitter http://twitter.com/#!/christocracy
    * @github https://github.com/christocracy
    */

  3. #3
    Ext User
    Join Date
    May 2009
    Posts
    5
    Vote Rating
    0
    curvatique is on a distinguished road

      0  

    Default


    Great, im looking forward to your insight. Trying to get the ext.direct specifications and philosophy crystal clear.

  4. #4
    Ext User
    Join Date
    Jul 2007
    Location
    Florida
    Posts
    9,996
    Vote Rating
    6
    mjlecomte will become famous soon enough mjlecomte will become famous soon enough

      0  

    Default


    FWIW I thought I read in the specifications something about the intent to go from array to object in the future?!

  5. #5
    Sencha User
    Join Date
    Apr 2009
    Location
    Bulgaria
    Posts
    21
    Vote Rating
    1
    ficeto is on a distinguished road

      0  

    Default


    I also tried the same grid and a different result:
    Code:
    {"action":"MySQL","method":"DirectGrid","data":["1754"],"type":"rpc","tid":4}
    and this was while using ext-all.js.
    i did some changes to Ext.data.DirectProxy.doRequest(), so i can really use all api options and even better, have a single directFn to deal with my stuff. so what i came up with is:
    PHP Code:
    doRequest : function(actionrsparamsreadercallbackscopeoptions) {
            var 
    args = [];
            var 
    directFn this.api[action] || this.directFn;
            
            switch (
    action) {
                case 
    Ext.data.Api.CREATE:
                    
    Ext.apply(params,{data:rs.data});
                    
    args.push(params);
                    break;
                case 
    Ext.data.Api.READ:
                    
    args.push(params);
                    break;
                case 
    Ext.data.Api.UPDATE:
                    
    Ext.apply(params,{data:rs.data});
                    
    args.push(params);
                    break;
                case 
    Ext.data.Api.DESTROY:
                    
    Ext.apply(params,{data:rs.data});
                    
    args.push(params);
                    break;
            }
            
    args.push(this.createCallback(actionreadercallbackscopeoptions));
            
    directFn.apply(windowargs);
        } 
    that way the request looks like:
    Code:
    {"action":"MySQL","method":"DirectGrid","data":[{"id":"1754","data":{"id":1754,"event":"PAUSEALLtwetw"
    ,"agent":"Agent/200","time":"2009-01-09T15:32:16","data":""},"xaction":"save","table":"queue_log"}],"type":"rpc","tid":4}
    which actually gives me all the data i might need.
    sad part is that i have to use ext-all-debug or i have to write a new class and include it every time i need to Ext.Direct a store

  6. #6
    Ext JS Premium Member christocracy's Avatar
    Join Date
    Oct 2006
    Location
    Montreal
    Posts
    381
    Vote Rating
    0
    christocracy is on a distinguished road

      0  

    Default


    The API of RC2 has some big changes from the version you're using. DirectProxy#doRequest now goes like this:

    Code:
    doRequest : function(action, rs, params, reader, callback, scope, options) {
            var args = [];
            var directFn = this.api[action] || this.directFn;
    
            switch (action) {
                case Ext.data.Api.actions.create:
                    args.push(params[reader.meta.root]);		// <-- create(Hash)
                    break;
                case Ext.data.Api.actions.read:
                    if(this.paramOrder){
                        for(var i = 0, len = this.paramOrder.length; i < len; i++){
                            args.push(params[this.paramOrder[i]]);
                        }
                    }else if(this.paramsAsHash){
                        args.push(params);
                    }
                    break;
                case Ext.data.Api.actions.update:
                    args.push(params[reader.meta.idProperty]);  // <-- save(Integer/Integer[], Hash/Hash[])
                    args.push(params[reader.meta.root]);
                    break;
                case Ext.data.Api.actions.destroy:
                    args.push(params[reader.meta.root]);        // <-- destroy(Int/Int[])
                    break;
            }
    
            var trans = {
                params : params || {},
                callback : callback,
                scope : scope,
                arg : options,
                reader: reader
            };
    
            args.push(this.createCallback(action, rs, trans), this);
            directFn.apply(window, args);
        },
    /**
    * @author Chris Scott
    * @business www.transistorsoft.com
    * @rate $150USD / hr; training $500USD / day / developer (5 dev min)
    *
    * @SenchaDevs http://senchadevs.com/developers/transistor-software
    * @twitter http://twitter.com/#!/christocracy
    * @github https://github.com/christocracy
    */

  7. #7
    Sencha User
    Join Date
    Apr 2009
    Location
    Bulgaria
    Posts
    21
    Vote Rating
    1
    ficeto is on a distinguished road

      0  

    Default


    OK!
    lots of changes here.....
    first, api method names are changed from:
    Code:
    api:{
    	load: myDirectFn,
    	create: myDirectFn,
    	save: myDirectFn,
    	destroy: E myDirectFn
    }
    to:
    Code:
    api:{
    	read: myDirectFn,
    	create: myDirectFn,
    	update: myDirectFn,
    	destroy: E myDirectFn
    }

    Also there is another thing: why would you create the possibility to use directFn if the number of arguments change and no type of action parameter is sent?

    what i mean is:
    read sends only parameter to directFn (or api.read) that is the params of the store (limit,order, baseParams, etc).
    create sends also only parameter which is the data created.
    update on other side sends two parameters which are the ID of the record updated and the data that was changed.
    and last but not least, destroy sends one parameter - ID of record deleted.
    using the Ext.Direct provider (i use the php backend), when defining a server side call to a method, we define the number of arguments it accepts, so it throws an exception when i try to send less arguments that it needs (if I define them as 2).

    so just to elaborate:
    directFn works if you don't intend to create,update or destroy any data (meaning you will only read data from the server), otherwise we need to use the api configuration object and expose 4 server side methods to manage the requests (sending xaction would have helped a bit)
    And, I still kinda like my approach ( which i need to revise a bit ). It works with directFn or api, and always passes one parameter to the directFn.