1. #1
    Sencha Premium Member
    Join Date
    Nov 2013
    Posts
    4
    Answers
    1
    Vote Rating
    1
    tlegault is on a distinguished road

      0  

    Default Answered: Local Grid Paging

    Answered: Local Grid Paging


    I am trying to enable paging in a Grid that uses a store that loads all data in a single server side request.

    How can this be done?

    My server side call is very fast, but I do not want all the data rendered in a single page in the browser.

    Is there a way to wrap a store into a paging store?

  2. Actually, I have found how to achieve what I want without relying on the remote server for paging.

    Essentially, when the first request is sent out to the store, I cache the parsed model objects. For subsequent releases, I clone the result set from the cached one, then re-apply all the filters, paging, etc in the getSubResultSet method.

    For the above store Rest proxy to work, you need to make sure this property is set on the store remoteSort : true. So the framework thinks its hitting the server for each page, but in reality this paging proxy uses the cached response to load subsequent pages.

    Code:
    Ext.define( 'Thomas.utils.LDPERestProxy',    {
            extend : 'Ext.data.proxy.Rest',
    
    
            loaded : false,
    
    
            fullResultSet : null,
    
    
            buildRequest : function( operation )
            {
                var request = this.callParent( arguments );
    
                return request;
            },
    
    
            doRequest : function( operation, callback, scope )
            {
                // Check if data already loaded
                if ( this.loaded )
                {
                    this.getSubResultSet( operation, callback, scope );
                    return;
                }
    
    
                this.callParent( arguments );
            },
    
    
            processResponse : function( success, operation, request, response, callback, scope )
            {
                var reader, result;
    
    
                if ( success === true )
                {
                    reader = this.getReader( );
    
    
                    // Apply defaults to incoming data only for read operations.
                    // For create and update, there will already be a client-side record
                    // to match with which will contain any defaulted in values.
                    reader.applyDefaults = operation.action === 'read';
    
    
                    result = reader.read( this.extractResponseData( response ) );
    
    
                    if ( result.success !== false )
                    {
                        // see comment in buildRequest for why we include the response
                        // object here
                        Ext.apply( operation,
                            {
                                response : response,
                                resultSet : result
                            } );
    
    
                        operation.commitRecords( result.records );
                        operation.setCompleted( );
                        operation.setSuccessful( );
                        this.fullResultSet = this.cloneResultSet( operation.resultSet );
                        this.loaded = true;
                    }
                    else
                    {
                        operation.setException( result.message );
                        this.fireEvent( 'exception', this, response, operation );
                    }
                }
                else
                {
                    this.setException( operation, response );
                    this.fireEvent( 'exception', this, response, operation );
                }
    
    
                // this callback is the one that was passed to the 'read' or 'write'
                // function above
                /*
                 * if (typeof callback == 'function') { callback.call(scope || me,
                 * operation); }
                 */
                this.getSubResultSet( operation, callback, scope );
    
    
                this.afterRequest( request, success );
            },
    
    
            read : function( operation, callback, scope )
            {
                if ( this.loaded )
                {
                    this.getSubResultSet( operation, callback, scope );
                    return;
                }
                this.callParent( arguments );
            },
    
    
            getSubResultSet : function( operation, callback, scope )
            {
                //alert( "get sub " + operation.limit );
                var resultSet = this.cloneResultSet( this.fullResultSet );
                operation.resultSet = resultSet;
                var records = resultSet.records;
                var sorters = operation.sorters;
                var groupers = operation.groupers;
                var filters = operation.filters;
    
    
                operation.setCompleted( );
    
    
                // Apply filters, sorters, and start/limit options
                if ( resultSet.success )
                {
    
    
                    // Filter the resulting array of records
                    if ( filters && filters.length )
                    {
                        records = resultSet.records = Ext.Array.filter( records, Ext.util.Filter.createFilterFn( filters ) );
                        resultSet.total = records.length;
                    }
    
    
                    // Remotely, groupers just mean top priority sorters
                    if ( groupers && groupers.length )
                    {
                        // Must concat so as not to mutate passed sorters array which
                        // could be the items property of the sorters collection
                        sorters = sorters ? sorters.concat( groupers ) : sorters;
                    }
    
    
                    // Sort by the specified groupers and sorters
                    if ( sorters && sorters.length )
                    {
                        resultSet.records = Ext.Array.sort( records, Ext.util.Sortable.createComparator( sorters ) );
                    }
    
    
                    // Reader reads the whole passed data object.
                    // If successful and we were given a start and limit, slice the
                    // result.
                    if ( operation.start !== undefined && operation.limit !== undefined )
                    {
                        // Attempt to read past end of memory dataset - convert to
                        // failure
                        if ( operation.start >= resultSet.total )
                        {
                            resultSet.success = false;
                            resultSet.count = 0;
                            resultSet.records =
                                [];
                        }
                        // Range is valid, slice it up.
                        else
                        {
                            resultSet.records = Ext.Array.slice( resultSet.records, operation.start, operation.start + operation.limit );
                            resultSet.count = resultSet.records.length;
                        }
                    }
                }
    
    
                if ( resultSet.success )
                {
                    operation.setSuccessful( );
                }
                else
                {
                    this.fireEvent( 'exception', me, null, operation );
                }
                Ext.callback( callback, scope || me,
                    [
                        operation
                    ] );
            },
    
    
            cloneResultSet : function( resultSet )
            {
                var config =
                    {
                        records : Ext.Array.clone( resultSet.records ),
                        count : resultSet.count,
                        loaded : resultSet.loaded,
                        success : resultSet.success,
                        total : resultSet.total
                    };
    
    
                return new Ext.data.ResultSet( config );
            }
        } );

  3. #2
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    8,935
    Answers
    656
    Vote Rating
    443
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      2  

    Default


    Paging is handled by remote data by sending only the records that you want to see on that page. It does not filter the data to show only the desired records for that page. If you want to send all of the data, then you would have to use a arrayStore and then set the pageSize and the proxy as follows:

    Code:
    var store = Ext.create('Ext.data.ArrayStore', { 
        fields: ['field', ... ],
        data: [] // your data
        pageSize: 10,
        proxy: {
            type: 'memory',
            enablePaging: true, // replaces PagingMemoryProxy functionality
            reader: {
                type: 'json',
                root: 'items'
            }
        }
    });

  4. #3
    Sencha Premium Member
    Join Date
    Nov 2013
    Posts
    4
    Answers
    1
    Vote Rating
    1
    tlegault is on a distinguished road

      1  

    Default Client Side Paging in Grid using Rest Proxy

    Client Side Paging in Grid using Rest Proxy


    Actually, I have found how to achieve what I want without relying on the remote server for paging.

    Essentially, when the first request is sent out to the store, I cache the parsed model objects. For subsequent releases, I clone the result set from the cached one, then re-apply all the filters, paging, etc in the getSubResultSet method.

    For the above store Rest proxy to work, you need to make sure this property is set on the store remoteSort : true. So the framework thinks its hitting the server for each page, but in reality this paging proxy uses the cached response to load subsequent pages.

    Code:
    Ext.define( 'Thomas.utils.LDPERestProxy',    {
            extend : 'Ext.data.proxy.Rest',
    
    
            loaded : false,
    
    
            fullResultSet : null,
    
    
            buildRequest : function( operation )
            {
                var request = this.callParent( arguments );
    
                return request;
            },
    
    
            doRequest : function( operation, callback, scope )
            {
                // Check if data already loaded
                if ( this.loaded )
                {
                    this.getSubResultSet( operation, callback, scope );
                    return;
                }
    
    
                this.callParent( arguments );
            },
    
    
            processResponse : function( success, operation, request, response, callback, scope )
            {
                var reader, result;
    
    
                if ( success === true )
                {
                    reader = this.getReader( );
    
    
                    // Apply defaults to incoming data only for read operations.
                    // For create and update, there will already be a client-side record
                    // to match with which will contain any defaulted in values.
                    reader.applyDefaults = operation.action === 'read';
    
    
                    result = reader.read( this.extractResponseData( response ) );
    
    
                    if ( result.success !== false )
                    {
                        // see comment in buildRequest for why we include the response
                        // object here
                        Ext.apply( operation,
                            {
                                response : response,
                                resultSet : result
                            } );
    
    
                        operation.commitRecords( result.records );
                        operation.setCompleted( );
                        operation.setSuccessful( );
                        this.fullResultSet = this.cloneResultSet( operation.resultSet );
                        this.loaded = true;
                    }
                    else
                    {
                        operation.setException( result.message );
                        this.fireEvent( 'exception', this, response, operation );
                    }
                }
                else
                {
                    this.setException( operation, response );
                    this.fireEvent( 'exception', this, response, operation );
                }
    
    
                // this callback is the one that was passed to the 'read' or 'write'
                // function above
                /*
                 * if (typeof callback == 'function') { callback.call(scope || me,
                 * operation); }
                 */
                this.getSubResultSet( operation, callback, scope );
    
    
                this.afterRequest( request, success );
            },
    
    
            read : function( operation, callback, scope )
            {
                if ( this.loaded )
                {
                    this.getSubResultSet( operation, callback, scope );
                    return;
                }
                this.callParent( arguments );
            },
    
    
            getSubResultSet : function( operation, callback, scope )
            {
                //alert( "get sub " + operation.limit );
                var resultSet = this.cloneResultSet( this.fullResultSet );
                operation.resultSet = resultSet;
                var records = resultSet.records;
                var sorters = operation.sorters;
                var groupers = operation.groupers;
                var filters = operation.filters;
    
    
                operation.setCompleted( );
    
    
                // Apply filters, sorters, and start/limit options
                if ( resultSet.success )
                {
    
    
                    // Filter the resulting array of records
                    if ( filters && filters.length )
                    {
                        records = resultSet.records = Ext.Array.filter( records, Ext.util.Filter.createFilterFn( filters ) );
                        resultSet.total = records.length;
                    }
    
    
                    // Remotely, groupers just mean top priority sorters
                    if ( groupers && groupers.length )
                    {
                        // Must concat so as not to mutate passed sorters array which
                        // could be the items property of the sorters collection
                        sorters = sorters ? sorters.concat( groupers ) : sorters;
                    }
    
    
                    // Sort by the specified groupers and sorters
                    if ( sorters && sorters.length )
                    {
                        resultSet.records = Ext.Array.sort( records, Ext.util.Sortable.createComparator( sorters ) );
                    }
    
    
                    // Reader reads the whole passed data object.
                    // If successful and we were given a start and limit, slice the
                    // result.
                    if ( operation.start !== undefined && operation.limit !== undefined )
                    {
                        // Attempt to read past end of memory dataset - convert to
                        // failure
                        if ( operation.start >= resultSet.total )
                        {
                            resultSet.success = false;
                            resultSet.count = 0;
                            resultSet.records =
                                [];
                        }
                        // Range is valid, slice it up.
                        else
                        {
                            resultSet.records = Ext.Array.slice( resultSet.records, operation.start, operation.start + operation.limit );
                            resultSet.count = resultSet.records.length;
                        }
                    }
                }
    
    
                if ( resultSet.success )
                {
                    operation.setSuccessful( );
                }
                else
                {
                    this.fireEvent( 'exception', me, null, operation );
                }
                Ext.callback( callback, scope || me,
                    [
                        operation
                    ] );
            },
    
    
            cloneResultSet : function( resultSet )
            {
                var config =
                    {
                        records : Ext.Array.clone( resultSet.records ),
                        count : resultSet.count,
                        loaded : resultSet.loaded,
                        success : resultSet.success,
                        total : resultSet.total
                    };
    
    
                return new Ext.data.ResultSet( config );
            }
        } );

Thread Participants: 1