PDA

View Full Version : Locked Grid and Buffered Renderer issues.



miroperez
18 Nov 2013, 3:26 PM
Ext version tested:

Ext 4.2.2.1144


Browser versions tested against:

IE8
FF25 (firebug 1.3.0.10 installed)
Chrome 31


DOCTYPE tested against:

____


Description:

WHen the bufferered renderer plugin is used with lockGridConfig the normal side of the grid scrolls indpendently from the locked side.


Steps to reproduce the problem:

create a locked grid what uses the lockedGridConfig and buffered rendered together.
https://fiddle.sencha.com/#fiddle/1lg

Fiddler code:


Ext.application({
name: 'Fiddle',

launch: function() {
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.form.field.Number',
'Ext.form.field.Date',
'Ext.tip.QuickTipManager',
'Ext.layout.container.Fit'
]);

Ext.define('Task', {
extend: 'Ext.data.Model',
idProperty: 'taskId',
fields: [
{name: 'projectId', type: 'int'},
{name: 'project', type: 'string'},
{name: 'taskId', type: 'int'},
{name: 'description', type: 'string', editor: 'textfield'},
{name: 'estimate', type: 'float'},
{name: 'rate', type: 'float'},
{name: 'due', type: 'date', dateFormat:'m/d/Y'}
]
});

var data = [
{projectId: 100, project: 'Ext Forms: Field Anchoring', taskId: 112, description: 'Integrate 2.0 Forms with 2.0 Layouts', estimate: 6, rate: 150, due:'06/24/2007'},
{projectId: 100, project: 'Ext Forms: Field Anchoring', taskId: 113, description: 'Implement AnchorLayout', estimate: 4, rate: 150, due:'06/25/2007'},
{projectId: 100, project: 'Ext Forms: Field Anchoring', taskId: 114, description: 'Add support for multiple types of anchors', estimate: 4, rate: 150, due:'06/27/2007'},
{projectId: 100, project: 'Ext Forms: Field Anchoring', taskId: 115, description: 'Testing and debugging', estimate: 8, rate: 0, due:'06/29/2007'},
{projectId: 101, project: 'Ext Grid: Single-level Grouping', taskId: 101, description: 'Add required rendering "hooks" to GridView', estimate: 6, rate: 100, due:'07/01/2007'},
{projectId: 101, project: 'Ext Grid: Single-level Grouping', taskId: 102, description: 'Extend GridView and override rendering functions', estimate: 6, rate: 100, due:'07/03/2007'},
{projectId: 101, project: 'Ext Grid: Single-level Grouping', taskId: 103, description: 'Extend Store with grouping functionality', estimate: 4, rate: 100, due:'07/04/2007'},
{projectId: 101, project: 'Ext Grid: Single-level Grouping', taskId: 121, description: 'Default CSS Styling', estimate: 2, rate: 100, due:'07/05/2007'},
{projectId: 101, project: 'Ext Grid: Single-level Grouping', taskId: 104, description: 'Testing and debugging', estimate: 6, rate: 100, due:'07/06/2007'},
{projectId: 102, project: 'Ext Grid: Summary Rows', taskId: 105, description: 'Ext Grid plugin integration', estimate: 4, rate: 125, due:'07/01/2007'},
{projectId: 102, project: 'Ext Grid: Summary Rows', taskId: 106, description: 'Summary creation during rendering phase', estimate: 4, rate: 125, due:'07/02/2007'},
{projectId: 102, project: 'Ext Grid: Summary Rows', taskId: 107, description: 'Dynamic summary updates in editor grids', estimate: 6, rate: 125, due:'07/05/2007'},
{projectId: 102, project: 'Ext Grid: Summary Rows', taskId: 108, description: 'Remote summary integration', estimate: 4, rate: 125, due:'07/05/2007'},
{projectId: 102, project: 'Ext Grid: Summary Rows', taskId: 109, description: 'Summary renderers and calculators', estimate: 4, rate: 125, due:'07/06/2007'},
{projectId: 102, project: 'Ext Grid: Summary Rows', taskId: 110, description: 'Integrate summaries with GroupingView', estimate: 10, rate: 125, due:'07/11/2007'},
{projectId: 102, project: 'Ext Grid: Summary Rows', taskId: 111, description: 'Testing and debugging', estimate: 8, rate: 125, due:'07/15/2007'}
];



Ext.tip.QuickTipManager.init();

var store = Ext.create('Ext.data.Store', {
model: 'Task',
data: data,
sorters: {property: 'due', direction: 'ASC'},
groupField: 'project'
});

// var cellEditing = Ext.create('Ext.grid.plugin.CellEditing', {
// clicksToEdit: 1
// });
var showSummary = true;
debugger;
var grid = Ext.create('Ext.grid.Panel', {
plugins: [{ // turning this on causing the locked side to stay fixed if the normal side is scrolled.
ptype: 'bufferedrenderer',
trailingBufferZone: 100, // Keep 150 rows rendered in the table behind scroll
leadingBufferZone: 100 // Keep 150 rows rendered in the table ahead of scroll
}],
lockedGridConfig: {
plugins: {
ptype: 'rowediting'
}
},
normalGridConfig: {
plugins: {
ptype: 'cellediting'
}
},
width: 800,
height: 450,
frame: true,
title: 'Sponsored Projects',
iconCls: 'icon-grid',
renderTo: document.body,
store: store,
//plugins: [cellEditing],
selModel: {
selType: 'cellmodel'
},
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
items: [{
tooltip: 'Toggle the visibility of the summary row',
text: 'Toggle Summary',
enableToggle: true,
pressed: true,
handler: function(){
showSummary = !showSummary;
var view = grid.lockedGrid.getView();
view.getFeature('group').toggleSummaryRow(showSummary);
view.refresh();
view = grid.normalGrid.getView();
view.getFeature('group').toggleSummaryRow(showSummary);
view.refresh();
}
}]
}],
features: [{
id: 'group',
ftype: 'groupingsummary',
groupHeaderTpl: '{name}',
hideGroupedHeader: true,
enableGroupingMenu: false
}],
columns: [{
text: 'Task',
width: 300,
locked: true,
tdCls: 'task',
sortable: true,
dataIndex: 'description',
editor: 'textfield',
hideable: false,
summaryType: 'count',
summaryRenderer: function(value, summaryData, dataIndex) {
return ((value === 0 || value > 1) ? '(' + value + ' Tasks)' : '(1 Task)');
}
}, {
header: 'Project',
width: 180,
sortable: true,
dataIndex: 'project'
}, {
header: 'Due Date',
width: 130,
sortable: true,
dataIndex: 'due',
summaryType: 'max',
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
summaryRenderer: Ext.util.Format.dateRenderer('m/d/Y'),
field: {
xtype: 'datefield'
}
}, {
header: 'Estimate',
width: 130,
sortable: true,
dataIndex: 'estimate',
summaryType: 'sum',
renderer: function(value, metaData, record, rowIdx, colIdx, store, view){
return value + ' hours';
},
summaryRenderer: function(value, summaryData, dataIndex) {
return value + ' hours';
},
field: {
xtype: 'numberfield'
}
}, {
header: 'Rate',
width: 130,
sortable: true,
renderer: Ext.util.Format.usMoney,
summaryRenderer: Ext.util.Format.usMoney,
dataIndex: 'rate',
summaryType: 'average',
field: {
xtype: 'numberfield'
}
}, {
header: 'Cost',
width: 130,
sortable: false,
groupable: false,
renderer: function(value, metaData, record, rowIdx, colIdx, store, view) {
return Ext.util.Format.usMoney(record.get('estimate') * record.get('rate'));
},
summaryType: function(records){
var i = 0,
length = records.length,
total = 0,
record;

for (; i < length; ++i) {
record = records[i];
total += record.get('estimate') * record.get('rate');
}
return total;
},
summaryRenderer: Ext.util.Format.usMoney
}]
});
}
});


The result that was expected:

Scrolling the normal side should also scroll the locked side.


The result that occurs instead:

Only the normal side scrolls. mousewheel on the locked side does scroll both grids.

Possible solution:
in Lockable.injectLockable something like this needs to happen:


....
lockedGrid = Ext.apply({
id: me.id + '-locked',
isLocked: true,
ownerLockable: me,
xtype: me.determineXTypeToCreate(true),
store: store,
scrollerOwner: false,


animate: false,

scroll: scrollbarHeight ? false : 'vertical',
selModel: selModel,
border: false,
cls: me.lockedGridCls,
isLayoutRoot: function() {
return false;
},
features: allFeatures.lockedFeatures,
//plugins: allPlugins.lockedPlugins <===== This will get stomped over by the me.lockedGridConfig.plugins so any plugins from allPlugins.lockedPlugins would be nuked.
}, me.lockedGridConfig);

// make sure you add any plugins from allPlugins.lockedPlugins into the lockedGrid.plugins
if(lockedGrid.plugins instanceof Array){
lockedGrid.plugins = lockedGrid.plugins.concat(allPlugins.lockedPlugins);
}else{
lockedGrid.plugins = [lockedGrid.plugins];
lockedGrid.plugins = lockedGrid.plugins.concat(allPlugins.lockedPlugins);
}

normalGrid = Ext.apply({
id: me.id + '-normal',
isLocked: false,
ownerLockable: me,
xtype: me.determineXTypeToCreate(),
store: store,
scrollerOwner: false,
selModel: selModel,
border: false,
isLayoutRoot: function() {
return false;
},
features: allFeatures.normalFeatures,
//plugins: allPlugins.normalPlugins <===== This will get stomped over by the me.lockedGridConfig.plugins so any plugins from allPlugins.normalPlugins would be nuked.
}, me.normalGridConfig);

// make sure you add any plugins from allPlugins.normalPlugins into the normalGrid.plugins
if(normalGrid.plugins instanceof Array){
normalGrid.plugins = normalGrid.plugins.concat(allPlugins.normalPlugins);
}else{
normalGrid.plugins = [normalGrid.plugins];
normalGrid.plugins = normalGrid.plugins.concat(allPlugins.normalPlugins);
}



The problem is the use of the Ext.apply() which is nuking any plugins from the first arg with the plugins from the second arg. It doesn't merge objects by design so last one wins which messes up the top level plugins. I will probably create a local override for this.

Gary Schlosberg
19 Nov 2013, 10:38 AM
Thanks for the report! I have opened a bug in our bug tracker.

miroperez
19 Nov 2013, 12:30 PM
Thanks for the report! I have opened a bug in our bug tracker.

btw, I created an override for Ext.grid.locking.Lockable,injectLockable() like this:



....
// Fixes inline. mperez.
lockedGrid = Ext.apply({
id: me.id + '-locked',
isLocked: true,
ownerLockable: me,
xtype: me.determineXTypeToCreate(true),
store: store,
scrollerOwner: false,


animate: false,

scroll: scrollbarHeight ? false : 'vertical',
selModel: selModel,
border: false,
cls: me.lockedGridCls,
isLayoutRoot: function() {
return false;
},
features: allFeatures.lockedFeatures
//plugins: allPlugins.lockedPlugins <===== This will get stomped over by the me.lockedGridConfig.plugins so any plugins from allPlugins.lockedPlugins would be nuked.
}, me.lockedGridConfig);

// Fix for plugins mperez
// make sure you add any plugins from allPlugins.lockedPlugins into the lockedGrid.plugins
if(lockedGrid.plugins){
if(lockedGrid.plugins instanceof Array){
lockedGrid.plugins = lockedGrid.plugins.concat(allPlugins.lockedPlugins);
}else{
lockedGrid.plugins = [lockedGrid.plugins];
lockedGrid.plugins = lockedGrid.plugins.concat(allPlugins.lockedPlugins);
}
}

normalGrid = Ext.apply({
id: me.id + '-normal',
isLocked: false,
ownerLockable: me,
xtype: me.determineXTypeToCreate(),
store: store,
scrollerOwner: false,
selModel: selModel,
border: false,
isLayoutRoot: function() {
return false;
},
features: allFeatures.normalFeatures
//plugins: allPlugins.normalPlugins <===== This will get stomped over by the me.lockedGridConfig.plugins so any plugins from allPlugins.normalPlugins would be nuked.
}, me.normalGridConfig);

// Fix for plugins mperez
// make sure you add any plugins from allPlugins.normalPlugins into the normalGrid.plugins
if(normalGrid.plugins){
if(normalGrid.plugins instanceof Array){
normalGrid.plugins = normalGrid.plugins.concat(allPlugins.normalPlugins);
}else{
normalGrid.plugins = [normalGrid.plugins];
normalGrid.plugins = normalGrid.plugins.concat(allPlugins.normalPlugins);
}
}

...

pscanlon1
20 Jun 2014, 9:21 AM
HAS THIS BEEN FIXED? 8 months? really?

rozenman
14 Jul 2015, 1:20 AM
Hey guys,Is there any patch that I can apply to fix this problem?

guilherme.lopes
15 Jun 2016, 4:40 PM
This is not a bug, when using multiple views (normal/locked) and plugins that should be added to both or only one of the views, the lockableScope config needs to be used.

So in this case, this would be the solution:

Replace this


plugins: [{
// turning this on causing the locked side to stay fixed if the normal side is scrolled.
ptype: 'bufferedrenderer',
trailingBufferZone: 100, // Keep 150 rows rendered in the table behind scroll
leadingBufferZone: 100 // Keep 150 rows rendered in the table ahead of scroll
}],
lockedGridConfig: {
plugins: {
ptype: 'rowediting'
}
},
normalGridConfig: {
plugins: {
ptype: 'cellediting'
}
}


with this



plugins: [{
// turning this on causing the locked side to stay fixed if the normal side is scrolled.
ptype: 'bufferedrenderer',
trailingBufferZone: 100, // Keep 150 rows rendered in the table behind scroll
leadingBufferZone: 100 // Keep 150 rows rendered in the table ahead of scroll
},{
ptype: 'rowediting',
lockableScope: 'locked'
},{
ptype: 'cellediting',
lockableScope: 'normal'
}]


This has been explained in the enableLocking config of the grid: http://docs.sencha.com/extjs/4.2.5/#!/api/Ext.grid.Panel-cfg-enableLocking