Page 1 of 2 12 LastLast
Results 1 to 10 of 15

Thread: Buffered Store - Fatal HasRange Call

    Success! Looks like we've fixed this one. According to our records the fix was applied for EXTJS-23373 in 6.2.2.
  1. #1
    Sencha Premium Member
    Join Date
    Aug 2013
    Location
    Chicago, IL
    Posts
    24
    Vote Rating
    11
      5  

    Default Buffered Store - Fatal HasRange Call

    Sencha,


    After upgrading to version 6, we noticed that our grids were no longer sortable. In fact, attempting to sort (column header click) seemed to generate a fatal error. The grid becomes completely unresponsive. After some break point digging, we traced the issue to a single line change made to the Ext.data.PageMap class hasRange method:


    Code:
      // 6.0.0.640 version
      // See - http://docs.sencha.com/extjs/6.0/6.0.0-classic/source/PageMap.html#Ext-data-PageMap-method-hasRange
      
     hasRange: function(start, end) {
            var me = this,
                pageNumber = me.getPageFromRecordIndex(start),
                endPageNumber = me.getPageFromRecordIndex(end);
    
    
            for (; pageNumber <= endPageNumber; pageNumber++) {
                if (!me.hasPage(pageNumber)) {
                    return false;
                }
            }
            // Check that the last page is filled enough to encapsulate the range.
            return (endPageNumber - 1) * me._pageSize + me.getPage(endPageNumber).length > end;
        },

    Note the gnarly return statement. This statement is new. Previously, it simply returned true


    Code:
    // 5.1.1.451 version
    // See  http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/source/PageMap.html#Ext-data-PageMap-method-hasRange
    
    
    hasRange: function(start, end) {
            var pageNumber = this.getPageFromRecordIndex(start),
                endPageNumber = this.getPageFromRecordIndex(end);
    
    
            for (; pageNumber <= endPageNumber; pageNumber++) {
                if (!this.hasPage(pageNumber)) {
                    return false;
                }
            }
            return true;
        },


    The new return statement blows up when the start or end input parameters are undefined or if the call to the getPage function is undefined. Based our testing, this can occur when you attempt to sort a grid panel bound to a buffered store. Requisite details including a simple workaround are outlined below.

    Thanks,


    @brady





    Stand Alone Test Case:





    Ext Version tested:


    Ext 6.0.0.640


    Browser version tested against:
    Chrome 44.0.2403.155 (64-bit)


    Description:


    See above.


    Steps to Reproduce:


    In the above fiddle try sorting a column of the grid.


    The result that was expected:


    Store is sorted.


    The result that occurs instead:


    Fatal framework level error is thrown and the application (or fiddle) simply stops working.


    Workaround:


    Added an Override class that restores the prior version of the hasRange method:


    Code:
    Ext.define('Overrides.data.PageMap', {
        override: 'Ext.data.PageMap',
        hasRange: function(start, end) {
            var pageNumber = this.getPageFromRecordIndex(start),
                endPageNumber = this.getPageFromRecordIndex(end);
            for (; pageNumber <= endPageNumber; pageNumber++) {
                if (!this.hasPage(pageNumber)) {
                    return false;
                }
            }
            return true;
        }
    });

  2. #2
    Sencha User
    Join Date
    Feb 2013
    Location
    California
    Posts
    11,985
    Vote Rating
    296
      0  

    Default

    Thanks for the report. Ext.data.PageMap is private, so I don't think it is meant to be used as in your test case.
    http://docs.sencha.com/extjs/6.0/6.0...t.data.PageMap

    I'm not sure what drove changing the return statement, but it seems to work in this example:
    http://examples.sencha.com/extjs/6.0...red-store.html

    What test behavior causes this to fail in your code? Do you have a test case with a store in it?

  3. #3
    Sencha Premium Member
    Join Date
    Aug 2013
    Location
    Chicago, IL
    Posts
    24
    Vote Rating
    11
      0  

    Default Updated Fiddle

    You are missing the point. That said, see the updated fiddle. The issue can occur if you define a store load listener and then from the handler (for whatever reason) need to initiate a store reload. The number of records in the store temporarily goes to zero and this causes the hasRange() function to blow up. There is simpler workaround. Specifically, you can add a buffer on the listener. This seems to do the trick in my case. But again, if the hasRange function (maybe) included an if statement, this upgrade problem could have been avoided. Another words, the hasRange function is (in my opinion) a bad function.

  4. #4
    Sencha Premium Member
    Join Date
    Dec 2013
    Posts
    34
    Vote Rating
    0
      0  

    Default

    Hi,

    We are also seeing a similar problem with 'hasRange' blowing up.

    For us, it seems to be related to layouts. I can get 'hasRange' to blow up if we setup a page with more than one border layout, or with a vbox layout inside a border layout.

    For example, if we have a page with centre and east regions, the east region being collapsed. Inside that east region is a panel with another border layout to give a centre and south region with agrid in the south region backed by a view model buffered store then as soon as you try and expand the collapsed outer east panel the 'hasRange' function blows up.

    Alternatively, if the east panel contains a simple panel with 'vbox' layout and the item is a grid then we can also get 'hasRange' to blow up.

    Changing the layout of the panel inside the east panel from 'border' to 'fit' or from 'vbox' to 'fit' makes the 'hasRange' problem go away.

    Additionally, '@brady', although your workaround seems to stop the error, i'm not sure that this is a solution. The hasRange function has obviously been changed for a reason and Sencha will be able to explain why. Using your workaround we get no error, but we also get zero records appearing in the grid even though the request has been made to the server and the data is sitting in the store.

    I have opened a support ticket with Sencha against ExtJS 6.0.1.250 and am currently awaiting a response. A fiddle which demonstrates the issue from a 'layouts' perspective can be seen here. Open dev tools before running to see the issue.

    https://fiddle.sencha.com/#fiddle/10d3

    Can we have an update please Sencha?

    Regards,
    Paul.

  5. #5
    Sencha User Daniil's Avatar
    Join Date
    Jun 2010
    Location
    Saint-Petersburg, Russia
    Posts
    1,018
    Vote Rating
    125
      0  

    Default

    Yeah, calling store.getRange() on a buffered store throws a JavaScript error.
    Uncaught TypeError: Cannot read property 'length' of undefined
    Though, maybe a .getRange() call without parameters is not supported for a buffered store.
    Object.NET
    Frameworks and Tools for .NET Developers
    --------------------------------------------------
    Ext.NET - Ext JS for ASP.NET - Examples | Twitter
    Bridge.NET - Write C#. Run JavaScript! - Live | Twitter
    --------------------------------------------------

  6. #6
    Sencha Premium Member
    Join Date
    Apr 2013
    Location
    Guildford, United Kingdom
    Posts
    11
    Vote Rating
    5
      0  

    Default

    We have the same issue when just displaying a list in the Modern toolkit. The start and end get set as NaN in the getRange method for the buffered store.

  7. #7
    Ext JS Premium Member tangix's Avatar
    Join Date
    Mar 2010
    Location
    Stockholm, Sweden
    Posts
    728
    Vote Rating
    81
      0  

    Default

    Thank you for this - spent a day troubleshooting and the override solves it in seconds. Sigh - this is sometimes the way of living with Ext JS...

  8. #8
    Sencha Premium User
    Join Date
    Aug 2014
    Location
    Auckland
    Posts
    46
    Vote Rating
    11
      0  

    Default

    Seeing something like this as well in 6.0.2

    Calling show on a grid with a buffered store in a floating container. Store has not loaded anything yet. AbstractView calls getViewRange, which calls getRange() with no parameters on the BufferedStore. This eventually results in NaN being passed to PageMap.hasRange.

    Relevant stack trace:
    Code:
    Ext.define.hasRange (PageMap.js:285) <-- "Cannot read property 'length' of undefined"
    Ext.define.rangeCached (BufferedStore.js:962)
    Ext.define.getRange (BufferedStore.js:443)
    Ext.define.getViewRange (AbstractView.js:988)
    Ext.Base.Base.addMembers.callParent (Base.js:1300)
    Ext.define.getViewRange (Table.js:3424)
    Ext.define.refresh (AbstractView.js:892)
    Ext.Base.Base.addMembers.callParent (Base.js:1300)
    Ext.define.refresh (View.js:768)
    Ext.Base.Base.addMembers.callParent (Base.js:1300)
    Ext.define.refresh (Table.js:2690)
    Ext.define.doFirstRefresh (AbstractView.js:1564)
    Ext.define.beforeLayout (AbstractView.js:606)
    Ext.define.init (ContextItem.js:243)
    Ext.define.invalidate (Context.js:676)
    Ext.define.invalidate (Context.js:734)
    Ext.define.invalidate (Context.js:734)
    Ext.define.flushInvalidates (Context.js:526)
    Ext.define.run (Context.js:1112)
    Ext.define.statics.flushLayouts (Component.js:208)
    Ext.define.statics.updateLayout (Component.js:271)
    Ext.define.updateLayout (Component.js:5732)
    Ext.define.onShow (Component.js:4572)
    Ext.define.show (Component.js:5428)

  9. #9
    Sencha Premium Member
    Join Date
    Dec 2013
    Posts
    34
    Vote Rating
    0
      0  

    Default

    Hi,

    Yes, we are seeing this in 6.0.2 as well. Something has definitely changed between 6.0.1 and 6.0.2 which has made this issue rear its ugly head again. We have opened another support ticket with Sencha regarding this, hopefully they will be able to provide an override. However, in the meantime I thought I would post this override that we have put together as we found that the above override for 'hasRange' was not the answer and there is a reason why they have changed the way that the return value is calculated. For us, this is only happening when using the SpreadsheetModel and it is only happening when there is some form of deselection event or where the PageMap causes a clear/reset of the selection. This lead us to the 'fireSelectionChange' method on the SpreadsheetModel and we could see that where there was nothing selected for a row selection the 'getRecords' method was dealing with this happily and returning an empty array to fire with the event. However, when the selection type is cells, 'getRange' is being used to return the range of records selected, even if there is no selection. This sounded very inefficient to us. If there is no selection then you simply return and empty array, there is no need to call 'getRange' at all. So, we changed this function to read as follows:

    Code:
    fireSelectionChange: function() {
        var me = this,
            grid = me.view.ownerGrid,
            sel = me.selected;
        // Inform selection object that we're done
    me.updateSelectionExtender();
        // We must still fire a selectionchange event through the SelectionModel because Ext.panel.Table listens for this event
        // to update its bound selection.
    if (sel.isRows) {
            me.fireEvent('selectionchange', me, sel.getRecords());
        } else if (sel.isCells) {
            me.fireEvent('selectionchange', me, sel.startCell === null || sel.endCell === null ? [] : me.store.getRange.apply(sel.view.dataSource, sel.getRowRange()));
        }
        grid.fireEvent('selectionchange', grid, sel);
    }
    Once we made this change (and left 'hasRange' as it is in 6.02) the problem went away for us.
    Will try and confirm on here if Sencha agree with our override.

    Hope that helps somebody.

    Paul.

  10. #10
    Sencha Premium User
    Join Date
    Apr 2011
    Posts
    49
    Vote Rating
    4
      0  

    Default

    I set the height, there is no question of a grid.
    If you do not set the height, it appeared the error.

Page 1 of 2 12 LastLast

Similar Threads

  1. Replies: 2
    Last Post: 2 Oct 2015, 3:47 PM
  2. Replies: 1
    Last Post: 4 Dec 2014, 9:51 AM
  3. Replies: 1
    Last Post: 18 Jun 2013, 2:39 PM
  4. Replies: 2
    Last Post: 10 Jun 2013, 2:24 AM
  5. buffered grid - buffered store in Ext 4.1b2
    By Moinsen in forum Ext: 4.x Beta
    Replies: 4
    Last Post: 6 Mar 2012, 5:16 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •