[CLOSED] Problem with paging...

Page 1 of 2 12 LastLast
  1. #1

    [CLOSED] Problem with paging...

    Hi,

    In a GridPanel of mine, I have a Store and a PagingToolbar. The Store uses a AjaxProxy. In the method that is called in the proxy I return a StoreResult.

    I don't want to do a count on my tables, so everytime I set the StoreResult.Total to int.MaxValue, except when i know its the last page. this way the button 'next page' stays able to click when i know it's not the last page and disable when i do, and i hide the 'last page' button.

    But when i put a number of page that don't exists (for example: 2222) and he tries to select data for that page (because it's within the total) I set the StoreResult.Success to false. This is enough to make the grid stay with the same rows but its like the store actually went to that page, because the Store.currentPage on js is the same page number that does not exists (in the example it would be 2222) and the PagingToolbar shows this page on the page 'selector'.

    There's someway to really cancel the page from 'turning' in my cenario?

    Example:
    //To build the Grid...
    {
        GridPanel grid = new GridPanel();
    
        Store store = new Store { ID = "test_store" };
    
        store.RemoteSort = true;
        store.PageSize = 33;
    
        AjaxProxy proxy = new AjaxProxy();
        proxy.StartParam = "startIndex";
        proxy.LimitParam = "pageSize";
        proxy.PageParam = "pageNumber";
        proxy.SortParam = "ordenacao";
        proxy.ActionMethods.Read = HttpMethod.POST;
    
        proxy.Reader.Add(new JsonReader { Root = "data", TotalProperty = "total", MessageProperty = "message" });
    
        proxy.Url = "/Entidade/CarregarRegistros/";
               
        store.Proxy.Add(proxy);
    
        grid.Store.Add(abastecedor);
    
        PagingToolbar pagingToolbar = new PagingToolbar { ID = "test_bar", HideRefresh = true };
    
        pagingToolbar.Listeners.BeforeRender.Handler = "this.getComponent('last').hidden = true;";
    
        pagingToolbar.AfterPageText = string.Empty;
    
        pagingToolbar.BeforePageText = string.Empty;
    
        pagingToolbar.DisplayMsg = "Records from {0} to {1}.";
    
        grid.BottomBar.Add(pagingToolbar);
    }
    
    //now for the proxy method...
    public StoreResult CarregarRegistros(int startIndex, int pageSize, int pageNumber, string ordenacao, string parametrosDeFiltro, string identificadorDaAplicacao)
    {
        StoreResult result = new StoreResult();
    
        IList<IEntidade> entityList = //Get the records from the DB, based on the page...
    
        if (entityList.Any())
        {
            int total;
    
            //IF the number of entities is smaller then the size of the page
            if (entityList.Count < pageSize)
            {
                //get the total based on the current page, because you are on the last one
                total = (pageNumber- 1) * pageSize+ entityList.Count;
            }
            //ELSE (still not the last page)
            else
            {
                //set total to max, because i don't know how many are (and i don't want to know)
                total = int.MaxValue;
            }
    
            result.Data = entityList;
            result.Total = total;
        }
        //ELSE (if there's no results, the page that he is searching does not exists)
        else
        {
            result.Success = false; // this does not cancel the page from turning, even the DisplayMsg of the toolbar has 'big numbers' on the {0} and {1}.
            result.Message = "There are no records on the page that you want to go.";
        }
    
        return result;
    }
    Thanks in advance,
    Last edited by Daniil; May 25, 2012 at 1:27 PM. Reason: [CLOSED]
  2. #2
    Hi,

    A bit strange scenario, I have never met such scenarios before. Please clarify is retrieving total records count so high-cost operation?

    There's someway to really cancel the page from 'turning' in my cenario?
    Well, I would prevent it on client returning false from Store BeforeLoad listener.
  3. #3
    Well...
    One of our tables has 26 millions rows... to apply a filtered search on a text column in this table is... expensive... and if we bring more than just the page, this operation could cost us more time than we are able to use...

    You see, i thought about the Store.BeforeLoad event too but, that means that I would have to select the filtered rows again to see if the page exists or not. And i would prefer not to do that...

    Edit: to be more precise, i did a count on the table i think its the biggest... SELECT count(*) FROM bigTable... 41.459.684 rows... and it took 00:00:42

    Thanks in advance,
  4. #4
    Quote Originally Posted by RCN View Post
    Well...
    One of our tables has 26 millions rows... to apply a filtered search on a text column in this table is... expensive... and if we bring more than just the page, this operation could cost us more time than we are able to use...

    Edit: to be more precise, i did a count on the table i think its the biggest... SELECT count(*) FROM bigTable... 41.459.684 rows... and it took 00:00:42
    Agreed, 42 seconds is too long. Did you try to optimize it? It's a common problem and there are many discussions on the internet, for example, this one:
    http://stackoverflow.com/questions/1...on-on-sql-serv

    As well, what about to organize counting on the database level? It would allow to just read the total amount from the database. For example, a trigger which would periodically count rows.

    Quote Originally Posted by RCN View Post
    You see, i thought about the Store.BeforeLoad event too but, that means that I would have to select the filtered rows again to see if the page exists or not. And i would prefer not to do that...
    I'm afraid I have not got why you don't want to use BeforeLoad and why you have to re-select rows. Could you provide more details? Maybe, a simple sample which would demonstrate the problem?
  5. #5
    It's not possible to add a trigger to count because the total of results that i will need to show its been filtered, so the total must be the total of records that match the search.
    but yes, we are trying to optimize everytime..

    As for the BeforeLoad... well, if i need the list of records that mach the search criteria to decide if that page exists or not (just like i'm doing in the proxy method), then, i'll have to do my search, and if the page exists, i'll return true and the proxy method will select then again.

    if you really need a example, i'll do it for you.

    like i said, with the success = false on the proxy the store page does not change the rows shown, than why it's like he changed pages? For me it's like a bug.. coz if i said that the search was not a success then why 'change' pages?

    Thanks in advance,
  6. #6
    Quote Originally Posted by RCN View Post
    It's not possible to add a trigger to count because the total of results that i will need to show its been filtered, so the total must be the total of records that match the search.
    but yes, we are trying to optimize everytime..
    Quote Originally Posted by RCN View Post
    As for the BeforeLoad... well, if i need the list of records that mach the search criteria to decide if that page exists or not (just like i'm doing in the proxy method), then, i'll have to do my search, and if the page exists, i'll return true and the proxy method will select then again.
    Clear, thanks for the clarification.

    Quote Originally Posted by RCN View Post
    like i said, with the success = false on the proxy the store page does not change the rows shown, than why it's like he changed pages? For me it's like a bug.. coz if i said that the search was not a success then why 'change' pages?
    Well, I would not consider it a bug, because PagingToolbar is not designed to deal with "wrong" total. Generally, your scenario is a bit specific.

    But I would agree, it can annoy that PagingToolbar is updated on unsuccessful load. And I won't be surprised it this behavior would change in some next ExtJS release.

    I can suggest the following solution to avoid it for now.

    Example
    Ext.toolbar.Paging.prototype.onLoad = Ext.Function.createInterceptor(Ext.toolbar.Paging.prototype.onLoad, function () {
        var success = arguments[2];
    
        return success;
    });
    Here is the full example.

    Example View
    <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
    
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Ext.Net.MVC v2 Example</title>
    
        <script type="text/javascript">
            Ext.toolbar.Paging.prototype.onLoad = Ext.Function.createInterceptor(Ext.toolbar.Paging.prototype.onLoad, function () {
                var success = arguments[2];
    
                return success;
            });
        </script>
    </head>
    <body>
        <ext:ResourceManager runat="server" />
    
        <ext:GridPanel ID="GridPanel1" runat="server" AutoHeight="true">
            <Store>
                <ext:Store runat="server" PageSize="3" ShowWarningOnFailure="false">
                    <Model>
                        <ext:Model runat="server">
                            <Fields>
                                <ext:ModelField Name="test" />
                            </Fields>
                        </ext:Model>
                    </Model>
                    <Proxy>
                        <ext:AjaxProxy Url="/Test/GetDataForRemotePaging">
                            <Reader>
                                <ext:JsonReader 
                                    Root="data" 
                                    TotalProperty="total" 
                                    MessageProperty="message" 
                                    ReadRecordsOnFailure="false"
                                    />
                            </Reader>
                        </ext:AjaxProxy>
                    </Proxy>
                </ext:Store>
            </Store>
            <ColumnModel runat="server">
                <Columns>
                    <ext:Column runat="server" Text="Test" DataIndex="test" />
                </Columns>
            </ColumnModel>
            <BottomBar>
                <ext:PagingToolbar runat="server" />
            </BottomBar>
        </ext:GridPanel>
    </body>
    </html>
    Example Controller Action
    public ActionResult GetDataForRemotePaging(int start, int limit)
    {
        List<object> data = this.MyData;
        if ((start + limit) > data.Count)
        {
            limit = data.Count - start;
        }
        List<object> rangeData = (start < 0 || limit < 0) ? data : data.GetRange(start, limit);
    
        StoreResult r = new StoreResult();
        r.Data = rangeData;
        r.Total = int.MaxValue;
    
        if (start >= 9)
        {
            r.Message = "No more records";
            r.Success = false;
        }
    
        return r;
    }
  7. #7
    Wow... never saw anything like that...

    Ok...

    I don't know why this happens but,
    the number of records in the DisplayMsg is now right ("Records from 1 to 30." when i change from page 1 to 222 in a page with size 30). ok.
    but the page number still 222. it's like that on the store.currentPage too (debugged the js).

    Thank you very much for your replys,
  8. #8
    Please clarify how can I reproduce the problem using my example? What are the steps?
  9. #9
    got to do a working sample. sry for the delay..
    <html>
    <head runat="server">
        <title>Test</title>
        <script type="text/javascript">
            Ext.toolbar.Paging.prototype.onLoad = Ext.Function.createInterceptor(Ext.toolbar.Paging.prototype.onLoad, function () {
                var success = arguments[2];
    
                return success;
            });
    
    
            var FalhaCargaDeRegistros = function (proxy, response, operation) {
    
                Ext.Msg.alert("Erro", operation.error);
    
                return true;
            }
    
        </script>
    </head>
    <body>
        <div>
            <ext:ResourceManager ID="ResourceManager1" runat="server" />
            <ext:GridPanel ID="GridPanel1" runat="server" AutoHeight="true">
                <Store>
                    <ext:Store ID="Store1" runat="server" PageSize="3" ShowWarningOnFailure="false">
                        <Listeners>
                            <Exception Handler="FalhaCargaDeRegistros(proxy, response, operation);">
                            </Exception>
                        </Listeners>
                        <Model>
                            <ext:Model ID="Model1" runat="server">
                                <Fields>
                                    <ext:ModelField Name="test" />
                                </Fields>
                            </ext:Model>
                        </Model>
                        <Proxy>
                            <ext:AjaxProxy Url="/Example/GetDataForRemotePaging/">
                                <Reader>
                                    <ext:JsonReader Root="data" TotalProperty="total" MessageProperty="message" ReadRecordsOnFailure="false" />
                                </Reader>
                            </ext:AjaxProxy>
                        </Proxy>
                    </ext:Store>
                </Store>
                <ColumnModel ID="ColumnModel1" runat="server">
                    <Columns>
                        <ext:Column ID="Column1" runat="server" Text="Test" DataIndex="test" />
                    </Columns>
                </ColumnModel>
                <BottomBar>
                    <ext:PagingToolbar ID="PagingToolbar1" runat="server" />
                </BottomBar>
            </ext:GridPanel>
        </div>
    </body>
    </html>
            public ActionResult GetDataForRemotePaging(int start, int limit)
            {
    
                StoreResult resultado = new StoreResult();
    
    
                int quantidadeDeRegistros = limit;
    
                int numeroDaPagina = (limit + start) / quantidadeDeRegistros;
    
                List<object> listaDeEntidades = new List<object> { new { test = "Page 1" }, new { test = "Page 1" }, new { test = "Page 1" } ,
                                                                   new { test = "Page 2" }, new { test = "Page 2" }, new { test = "Page 2" } ,
                                                                   new { test = "Page 3" }, new { test = "Page 3" }, new { test = "Page 3" } };
    
                if (listaDeEntidades.Count > start)
                {
                    int quantidadeNaUltimaPagina = (listaDeEntidades.Count - start);
    
                    if (quantidadeNaUltimaPagina > limit)
                    {
                        quantidadeNaUltimaPagina = limit;
                    }
    
                    listaDeEntidades = listaDeEntidades.GetRange(start, quantidadeNaUltimaPagina);
                }
                else
                {
                    listaDeEntidades = new List<object>();
                }
    
                //Se retornou algum resultado
                if (listaDeEntidades.Any())
                {
                    //Cria variável que irá armazenar o total de entidades na lista até o momento
                    int total;
    
                    //Se a quantidade de elementos na lista de entidades é menor que tamanho da página
                    if (listaDeEntidades.Count < quantidadeDeRegistros)
                    {
                        //Total é igual ao número de entidades nas páginas anteriores mais o número de entidades nessa página
                        total = (numeroDaPagina - 1) * quantidadeDeRegistros + listaDeEntidades.Count;
                    }
                    //Se a quantidade de elementos na lista de entidades é igual ao tamanho da página
                    else
                    {
                        //Total é igual ao máximo valor possível de elementos pois não sabemos nesse momento quantas páginas faltam
                        total = int.MaxValue;
                    }
    
                    //Atribui como data a lista de entidade
                    resultado.Data = listaDeEntidades;
                    //Atribui o total como sendo o total calculado acima
                    resultado.Total = total;
                }
                //Se não houver resultados
                else
                {
                    resultado.Success = false;
                    resultado.Message = "Theres no records on the page you selected to go.";
                }
    
                return resultado;
            }
    like i said:
    the number of records in the DisplayMsg is now right ("Records from 1 to 3." when i change from page 1 to 222 in a page with size 3). ok.
    but the page number still 222. it's like that on the store.currentPage too (debugged the js in the exception handler).

    Thanks for everything,
  10. #10
    I can suggest the following solution.

    Markup
    <ext:PagingToolbar runat="server">
        <Listeners>
            <BeforeChange Handler="this.pageToRestore = this.getStore().currentPage;" />
        </Listeners>
    </ext:PagingToolbar>
    JavaScript
    Ext.toolbar.Paging.prototype.onLoad = Ext.Function.createInterceptor(Ext.toolbar.Paging.prototype.onLoad, function () {
        var success = arguments[2];
    
        if (success === false) {
            this.child("#inputItem").setRawValue(this.pageToRestore);
            this.getStore().currentPage = this.pageToRestore;
        }
     
        return success;
    });
    By the way, it also happens if change pages by the Next button - store.currentPage was increased. It has been also fixed with the solution above.

    Though I am not sure there won't be any backstage effects. Maybe, it would be better to explicitly load a previous valid page.

    Example
    Ext.toolbar.Paging.prototype.onLoad = Ext.Function.createInterceptor(Ext.toolbar.Paging.prototype.onLoad, function () {
        var success = arguments[2];
    
        if (success === false) {
            this.getStore().loadPage(this.pageToRestore);
        }
     
        return success;
    });
    Last edited by Daniil; May 25, 2012 at 10:06 AM.
Page 1 of 2 12 LastLast

Similar Threads

  1. [CLOSED] MVC Grid Problem Paging
    By adelaney in forum 2.x Legacy Premium Help
    Replies: 3
    Last Post: May 16, 2012, 7:55 PM
  2. Problem with paging
    By oseqat in forum 1.x Help
    Replies: 16
    Last Post: Jul 01, 2011, 10:50 PM
  3. Problem with paging toolbar
    By sonnh11 in forum 1.x Help
    Replies: 3
    Last Post: May 10, 2011, 12:08 PM
  4. [CLOSED] problem with Json Paging.
    By farisqadadeh in forum 1.x Legacy Premium Help
    Replies: 2
    Last Post: Jan 22, 2011, 5:20 PM
  5. Paging ToolBar Problem
    By kiran malgi in forum 1.x Help
    Replies: 2
    Last Post: Mar 29, 2010, 8:25 AM

Tags for this Thread

Posting Permissions