PDA

View Full Version : [FIXED] Event sequence grid/view/selectionmodel not correct



tvanzoelen
22 Jun 2011, 2:24 AM
REQUIRED INFORMATION


Ext version tested:

Ext 4.0.2a


Browser versions tested against:

IE9
FF3 FF6
Chrome


Description:

The beforeselect event on the selectionmodel is triggered before the itemkeydown on the gridview.


Steps to reproduce the problem:

See and run the code example. If you press the item key down on the grid you see first the beforeselect alert.



The result that was expected:

Most logically the beforeitemkeydown event should occur before the beforeselect event on the selectionmodel. This because the itemkeydown action is the trigger for select, you should be able to block this action if wanted.



The result that occurs instead:

The select event is fired before its trigger action (itemkeydown) is fired.



Test Case:



Ext.onReady(function() {
Ext.tip.QuickTipManager.init();

// Store creation
Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name', 'email', 'phone'],
data: { 'items': [
{ "name": "Lisa", "email": "lisa@simpsons.com", "phone": "555-111-1224" },
{ "name": "Bart", "email": "bart@simpsons.com", "phone": "555--222-1234" },
{ "name": "Homer", "email": "home@simpsons.com", "phone": "555-222-1244" },
{ "name": "Marge", "email": "marge@simpsons.com", "phone": "555-222-1254" }
]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
});

var gridpanel = Ext.create('Ext.grid.Panel', {
id: 'gridpanel',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
columns: [
{ header: 'Name', dataIndex: 'name' },
{ header: 'Email', dataIndex: 'email', flex: 1 },
{ header: 'Phone', dataIndex: 'phone' }
]
});


gridpanel.on('render', function(t) {

gridpanel.getView().on('beforeitemkeydown', function(view, record, item, index, e, r) {

//gridpanel.getView().getSelectionModel().suspendEvents();
alert('beforeitemkeydown');
});
});

gridpanel.getSelectionModel().on('beforeselect', function(selectionModel, record, index, options) {

alert('beforeselect');

});


var panel = Ext.create('Ext.panel.Panel',
{
title: 'A panel with grid',
height: '400px',
width: '400px',
border: true,
renderTo: Ext.getBody(),
items: [gridpanel]
});

});







Possible fix:

Hack the itemkeydown event in the SelectionModel.



Operating System:

Win Vista

mike.estes
23 Jun 2011, 1:36 PM
thanks for the report, we've just introduced a new bug template that will help us migrate bugs from the forums to our bug tracker. Could you please update your ticket to follow this template (http://www.sencha.com/forum/showthread.php?138165-How-to-report-a-bug) so that we can address it faster?

Qanik
28 Jul 2011, 6:28 AM
This bug is still present in 4.0.4.

tvanzoelen
19 Aug 2011, 3:49 AM
I have put the bug in the correct template format as you've desired.

Terence

grace.mylasso
30 Aug 2011, 12:48 PM
The bug report has now been entered in the proper format by tvanzoelen (http://www.sencha.com/forum/member.php?32684-tvanzoelen) and the "Wait! Looks like we don't have enough information to add this to bug database. Please follow this template bug format. (http://www.sencha.com/forum/showthread.php?138165-How-to-report-a-bug)" message is still showing on this thread. Is there something else that still needs to be added for this to become a bug?

I think this is related to my current issue and would like a confirmation of this thread's report as a bug and an ETA on a fix. I'm trying to prevent the user from selecting certain items on a grid, but I'm unable to block this selection with even this example (on an Ext.grid.Panel) that always returns false:


listeners: {
beforeselect: function(view, node) {
return false;
}
}


EDIT:
It turns out that the beforeselect is actually working. The item selection is correctly being prevented. However, it remains highlighted. Due to the similarities in colour/UI for 'selected' versus 'highlighted', it was difficult to tell what was actually going on.

I'm not sure if it's a bug that the highlight is not automatically removed when selection is prevented. For my particular UI scenario, it makes sense to not highlight an item that is not selected by the user. Just like it seemed to me that the item was being selected, the user might also think they've selected an item that they haven't.


listeners: {
beforeselect: function(view, node) {
node.clearHighlight();
return false;
}
}

Animal
19 Nov 2011, 12:22 AM
OK, the solution I came up with was to refactor KeyMap to accept a Component as well as an Element as its key event source.

You can also provide the name of the event, and a processEvent method which accepts an event with multiple args, and just returns the event (You can return false from that which cancels the processing right there)

Also, KeyMap and KeyNav have been updated to use the standard single parameter constructor with a config object (Though they will accept the multiple arg form which will be deprecated in V5)

So for instance, you can now do:



var map = new Ext.util.KeyMap({
target: myGridView,
eventName: 'itemkeydown',
processEvent: function(view, record, node, index, event) {

// Load the event with the extra information needed by the mappings
event.view = view;
event.store = view.getStore();
event.record = record;
event.index = index;
return event;
},
binding: {
key: Ext.EventObject.DELETE,
fn: function(keyCode, e) {
e.store.remove(e.record);

// Attempt to select the record that's now in its place
e.view.getSelectionModel().select(e,index);
e.view.el.focus();
}
}
});


RowSelectionModel now uses an itemkeydown listener which means that if an app returns false from a beforeitemkeydown listener, navigation can be canceled. Which is great because RowSelectionModel now receives more information injected into its event by a custom processEvent method.

tvanzoelen
16 Jan 2012, 12:54 AM
This one seems solved in 4.1[Beta]

Anyway, thankx for the reply Animal.

tvanzoelen
16 Feb 2012, 1:59 AM
The keydown listener is solved in beta2, but the selectevent cycle is still not correct.

If I return false on a beforerowselect the selectevent isn't fired, but somehow it makes the selection. In the sample below getLastSelection returns the record wich I cancelled in beforeRowSelect. It also focusses the clicked row if it was a new selection.

This behaviour is new in 4.1. I think it should not focus the clicked row and the clicked record should not be returned with getLastSelection.

What I want is to cancel the selection (the previous row should remain focussed), but I also want to know the clicked row to procede later on with the selection.




Ext.onReady(function() {
Ext.tip.QuickTipManager.init();

// Store creation
Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name', 'email', 'phone'],
data: { 'items': [
{ "name": "Lisa", "email": "lisa@simpsons.com", "phone": "555-111-1224" },
{ "name": "Bart", "email": "bart@simpsons.com", "phone": "555--222-1234" },
{ "name": "Homer", "email": "home@simpsons.com", "phone": "555-222-1244" },
{ "name": "Marge", "email": "marge@simpsons.com", "phone": "555-222-1254" }
]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
});

var gridpanel = Ext.create('Ext.grid.Panel', {
id: 'gridpanel',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
title: 'A grid',
multiSelect: true,
columns: [
{ header: 'Name', dataIndex: 'name' },
{ header: 'Email', dataIndex: 'email', flex: 1 },
{ header: 'Phone', dataIndex: 'phone' }
]
});


gridpanel.getSelectionModel().on('beforeselect', function(selectionModel, record, index, options) {

var lastSelected = gridpanel.getSelectionModel().getLastSelected();
alert(lastSelected.data.name);
return false;
//alert('beforerowselect');
});

gridpanel.getSelectionModel().on('beforeselect', function(selectionModel, record, index, options) {

var lastSelected = gridpanel.getSelectionModel().getLastSelected();
alert(lastSelected.data.name);
return false;
//alert('beforerowselect');
});

gridpanel.getSelectionModel().on('select', function(selectionModel, record, index, options) {
alert('rowselect');
});



var panel = Ext.create('Ext.panel.Panel',
{
height: '400',
width: '400',
border: true,
title: 'click a row twice',
renderTo: Ext.getBody(),
items: [gridpanel]
});

});