Results 1 to 4 of 4

Thread: Column width issue in grid with bufferedrenderer and rowexpander plugins

  1. #1
    Sencha Premium Member
    Join Date
    Jun 2012
    Posts
    19

    Default Column width issue in grid with bufferedrenderer and rowexpander plugins

    Using a grid with plugins bufferedrenderer and rowexpander. The column widths break when new rows render on scroll (see screenshot.) I've tried several combinations of settings and fixed column widths to force the columns to size on scroll but no success. If I remove the rowexpander then the columns size fine. Is there a way to force proper rendering of new rows?

    Reproducible in all browsers with a simple MVC app.

    Using ExtJS 4.2.1.744

    Code:
    Ext.define("MyApp.view.Users", {
      extend: 'Ext.grid.Panel',
      alias: 'widget.userlist',
    
    
      title: 'All Users',
    
    
      plugins: [
        {
          ptype: 'bufferedrenderer',
          trailingBufferZone: 20,  // Keep 20 rows rendered in the table behind scroll   
          leadingBufferZone: 50   // Keep 50 rows rendered in the table ahead of scroll
        },{
        ptype: 'rowexpander',
        rowBodyTpl : new Ext.XTemplate(
          '<p><b>ID:</b> {id}</p>',
          '<p><b>Name:</b> {firstname} {lastname}</p><br>'
        )
      }],
    
    
      initComponent: function() {
          this.store = {
              fields: ['id', 'firstname', 'lastname', 'address', 'email',
                       'company', 'country', 'desc'],
              data  : [ 
                {LOTS OF DUMMY DATA}
              ]
           };
    
    
            this.columns = [
                {header: 'ID',  dataIndex: 'id',  flex: 1},
                {header: 'Company',  dataIndex: 'company',  flex: 1},
                {header: 'First Name',  dataIndex: 'firstname',  flex: 1},
                {header: 'Last Name',  dataIndex: 'lastname',  flex: 1},
                {header: 'Email',  dataIndex: 'email',  flex: 1},
                {header: 'Address',  dataIndex: 'address',  flex: 1},
                {header: 'Country',  dataIndex: 'country',  flex: 1},
                {header: 'Desc',  dataIndex: 'desc',  flex: 1}
            ];
    
    
            this.callParent(arguments);
        }
    });
    Screenshot from Chrome 27.0.1453.110:

    buffered-grid-rowexpand-render-issue.png

  2. #2
    Sencha User slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    6,165

    Default

    I see the issue in 4.2.1.744 (Beta), but looks like the issue was fixed by 4.2.1 general release.

    Code:
    Ext.define('Employee', {
        extend: 'Ext.data.Model',
        fields: [{
            name: 'employeeNo'
        }, {
            name: 'rating',
            type: 'int'
        }, {
            name: 'salary',
            type: 'float'
        }, {
            name: 'forename'
        }, {
            name: 'surname'
        }, {
            name: 'email'
        }, {
            name: 'department'
        }, {
            name: 'dob',
            type: 'date',
            dateFormat: 'Ymd'
        }, {
            name: 'joinDate',
            type: 'date',
            dateFormat: 'Ymd'
        }, {
            name: 'noticePeriod'
        }, {
            name: 'sickDays',
            type: 'int'
        }, {
            name: 'holidayDays',
            type: 'int'
        }, {
            name: 'holidayAllowance',
            type: 'int'
        }],
        idField: 'employeeNo'
    });
    
    
    function random(from, to) {
        return Math.floor(Math.random() * (to - from + 1) + from);
    }
    
    
    function getEmployeeNo() {
        var out = '',
            i = 0;
        for (; i < 6; ++i) {
            out += random(0, 7);
        }
        return out;
    }
    
    
    /**
     * Returns an array of fake data
     * @param {Number} count The number of fake rows to create data for
     * @return {Array} The fake record data, suitable for usage with an ArrayReader
     */
    function createFakeData(count, data) {
        var firstNames   = ['Ed', 'Tommy', 'Aaron', 'Abe', 'Jamie', 'Adam', 'Dave', 'David', 'Jay', 'Nicolas', 'Nige'],
            lastNames    = ['Spencer', 'Maintz', 'Conran', 'Elias', 'Avins', 'Mishcon', 'Kaneda', 'Davis', 'Robinson', 'Ferrero', 'White'],
            departments  = ['Engineering', 'Sales', 'Marketing', 'Managment', 'Support', 'Administration'],
            ratings      = [1, 2, 3, 4, 5],
            salaries     = [100, 400, 900, 1500, 1000000],
            noticePeriods= ['2 weeks', '1 month', '3 months'],
            i;
    
    
        for (i = 0; i < (count || 25); i++) {
            var firstName   = firstNames[random(0, firstNames.length - 1)],
                lastName    = lastNames[random(0, lastNames.length - 1)],
                name        = Ext.String.format("{0} {1}", firstName, lastName),
                email       = firstName.toLowerCase() + '.' + lastName.toLowerCase() + '@sentcha.com',
                rating      = ratings[(name === 'Nige White') ? 0 : random(0, ratings.length - 1)],
                salary      = salaries[(name === 'Nige White') ? 4 : random(0, salaries.length - 1)],
                department  = departments[random(0, departments.length - 1)],
                ageInYears  = random(23, 55),
                dob         = new Date(new Date().getFullYear() - ageInYears, random(0, 11), random(0, 31)),
                joinDate    = new Date(new Date() - random(60, 2000) * 1000 * 60 * 60 * 24),
                sickDays    = random(0, 10),
                holidayDays = random(0, 10),
                holidayAllowance = random(20, 40);
    
    
            data.push({
                employeeNo: getEmployeeNo(),
                rating: rating,
                salary: salary,
                forename: firstName,
                surname: lastName,
                email: email,
                department: department,
                dob: dob,
                joinDate: joinDate,
                sickDays: sickDays,
                holidayDays: holidayDays,
                holidayAllowance: holidayAllowance,
                noticePeriod: noticePeriods[random(0, noticePeriods.length - 1)]
            });
        }
    }
    
    
    // Create the Data Store.
    // Because it is buffered, the automatic load will be directed
    // through the prefetch mechanism, and be read through the page cache
    var store = Ext.create('Ext.data.Store', {
        groupField: 'department',
        model: 'Employee'
    });
    
    
    var jumpToRow = function(){
        var fld = grid.down('#gotoLine');
        if (fld.isValid()) {
            grid.view.bufferedRenderer.scrollTo(fld.getValue() - 1, true);
        }    
    };
    
    
    var data = [],
        perBatch = 1000,
        max = 5000;
    
    
    var grid = Ext.create('Ext.grid.Panel', {
        width: 700,
        height: 500,
        title: 'Buffered Grid of 5,000 random records',
        store: store,
        loadMask: true,
        plugins: [{
            ptype: 'bufferedrenderer',
            trailingBufferZone: 20, // Keep 20 rows rendered in the table behind scroll   
            leadingBufferZone: 50 // Keep 50 rows rendered in the table ahead of scroll
        }, {
            ptype: 'rowexpander',
            rowBodyTpl: new Ext.XTemplate(
                '<p><b>ID:</b> {employeeNo}</p>',
                '<p><b>Name:</b> {forename} {surname}</p><br>'
            )
        }],
        selModel: {
            pruneRemoved: false
        },
        viewConfig: {
            trackOver: false
        },
        features: [{
            ftype: 'groupingsummary',
            groupHeaderTpl: 'Department: {name}',
            showSummaryRow: false
        }],
        // grid columns
        columns:[{
            xtype: 'rownumberer',
            width: 40,
            sortable: false
        }, {
            text: 'Id',
            sortable: true,
            dataIndex: 'employeeNo',
            groupable: false,
            width: 70
        }, {
            text: 'Name',
            sortable: true,
            dataIndex: 'name',
            groupable: false,
            renderer: function(v, cellValues, rec) {
                return rec.get('forename') + ' ' + rec.get('surname');
            },
            width: 120
        }, {
            text: 'Date of birth',
            dataIndex: 'dob',
            xtype: 'datecolumn',
            groupable: false
        }, {
            text: 'Join date',
            dataIndex: 'joinDate',
            xtype: 'datecolumn',
            groupable: false
        }, {
            text: 'Notice period',
            dataIndex: 'noticePeriod',
            groupable: false
        }, {
            text: 'Email address',
            dataIndex: 'email',
            width: 200,
            groupable: false,
            renderer: function(v) {
                return '<a href="mailto:' + v + '">' + v + '</a>';
            }
        }, {
            text: 'Department',
            dataIndex: 'department',
            hidden: true,
            hideable: false,
            groupable: false
        }, {
            text: 'Absences',
            columns: [{
                text: 'Illness',
                dataIndex: 'sickDays',
                width: 60,
                groupable: false
            }, {
                text: 'Holidays',
                dataIndex: 'holidayDays',
                width: 70,
                groupable: false
            }, {
                text: 'Holday Allowance',
                dataIndex: 'holidayAllowance',
                width: 125,
                groupable: false
            }]
        }, {
            text: 'Rating',
            width: 70,
            sortable: true,
            dataIndex: 'rating',
            groupable: false
        }, {
            text: 'Salary',
            width: 110,
            sortable: true,
            dataIndex: 'salary',
            align: 'right',
            renderer: Ext.util.Format.usMoney,
            groupable: false
        }],
        bbar: [{
            labelWidth: 80,
            fieldLabel: 'Jump to row',
            xtype: 'numberfield',
            minValue: 1,
            maxValue: max,
            allowDecimals: false,
            itemId: 'gotoLine',
            enableKeyEvents: true,
            listeners: {
                specialkey: function(field, e){
                    if (e.getKey() === e.ENTER) {
                        jumpToRow();
                    }
                }
            }
        }, {
            text: 'Go',
            handler: jumpToRow
        }],
        renderTo: Ext.getBody()
    });
    
    
    function makeData() {
        createFakeData(perBatch, data);
        if (data.length < max) {
            setTimeout(makeData, 10);
        } else {
            Ext.getBody().unmask();
            store.loadData(data);
        }
    }
    
    
    Ext.getBody().mask('Generating fake data...');
        
    // In old IE, the fake data loop can cause a slow script warning,
    // so kick this off in the "background" to load the data in chunks.
    makeData();

  3. #3
    Sencha Premium Member
    Join Date
    Jan 2011
    Location
    London, UK
    Posts
    50

    Default 4.2.883 and IE8 still a problem

    I see this issue in 4.2.883 but only when
    - using IE8 (the majority of our users )
    - the grid is narrow enough that column content overflows the cells (or there are loads of columns in a wide grid)

    The amount of 'bad offset' that is introduced into the columns looks like it is relative to the amount of overflow.
    i.e. the narrower you make the grid the worse it looks.

    I can reproduce this using the Neptune theme and this code:

    Code:
    Ext.define('BPCSP.view.bugs.Grid', {    extend: 'Ext.grid.Panel',
        alias: 'widget.bugs_grid',
        title: 'All Users',
        plugins: [
        {
            ptype: 'bufferedrenderer',
            variableRowHeight: false,
            trailingBufferZone: 20,
            leadingBufferZone: 50
        }, {
            ptype: 'rowexpander',
            rowBodyTpl: new Ext.XTemplate('Hello')
        }],
    
        initComponent: function() {
            var data = [], i = 0;
    
            do{
                i++;
                data.push({
                    'id': 'id ' + i,
                    'date': new Date(),
                    'company': i%2 === 0   ? 'Sencha' : 'ExtJs',
                    'firstname': i%3 === 0 ? 'Alice': 'Ben',
                    'lastname': i%4 === 0  ? 'Smith': 'Andersen-Jones',
                    'email': i%5 === 0     ? '[email protected]' : '[email protected]',
                    'address': i%6 === 0   ? 'address': 'longer address',
                    'country': 'UK'
                });
            } while (i < 500);
    
            this.store = {
                fields: [
                    'id',
                    'company',
                    'firstname',
                    'lastname',
                    'address',
                    'email',
                    'country',
                    'date'
                ],
                data  : data
            };
    
            this.columns = [
                {header: 'ID',  dataIndex: 'id',  flex: 1},
                {header: 'Company',  dataIndex: 'company',  flex: 1},
                {header: 'First Name',  dataIndex: 'firstname',  flex: 1},
                {header: 'Last Name',  dataIndex: 'lastname',  flex: 1},
                {header: 'Email',  dataIndex: 'email',  flex: 1},
                {header: 'Address',  dataIndex: 'address',  flex: 1},
                {header: 'Country',  dataIndex: 'country',  flex: 1}
            ];
    
            this.callParent(arguments);
        }
    });
    Wider grid all behaves well.
    Wide Grid - scroll down - all fine.png


    Narrower grid - resize browser - the scroll - it all breaks.

    Narrow grid - scroll down - BROKEN.png


    The buffered renderer does such a great job - but this issue has caused a lot of upset on our project - with some folk even mentioning Flex as a replacement!!!!!!!!

    Cheers,

    Cathy

  4. #4

    Default A bad fix of this issue

    viewready:function( me, eOpts ){
    var grid= Ext.getCmp('companyView');
    grid.view.getEl().on('scroll',function(){
    var grid= Ext.getCmp('companyView');
    grid.doComponentLayout( );
    });

    }

    I have used grid.doComponentLayout( ); on scroll of the grid ....
    please let me know if anybody has any better solution .

Posting Permissions

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