PDA

View Full Version : Grid column 'renderer' question



abcdef
15 Aug 2011, 12:26 PM
I have a grid (takes a while for its store to load - so its masked till it loads completely) with 1 column renderer. I have a div with a certain class name as part of what the renderer returns. I need to show a slider when the user hovers over that div. How do I achieve this?

Thanks in advance!

slemmon
15 Aug 2011, 2:40 PM
You might add a listener to the div containers to show a slider with floating: true there at the cursor's position. You don't want to attach too many listeners to html elements so for the divs you can set up your listeners using a delegate property. There's actually a pretty decent example of this in the API docs under Element > On.
http://docs.sencha.com/ext-js/4-0/#/api/Ext.Element-method-on

If that doesn't get you going just post back and maybe include your renderer code snippet and maybe we can get an example going for you.

slemmon
15 Aug 2011, 2:42 PM
I say we meaning on of your helpful peers on the community forums (me or one of the even more clever helpful hands). ;)

abcdef
15 Aug 2011, 3:02 PM
You might add a listener to the div containers to show a slider with floating: true there at the cursor's position. You don't want to attach too many listeners to html elements so for the divs you can set up your listeners using a delegate property. There's actually a pretty decent example of this in the API docs under Element > On.
http://docs.sencha.com/ext-js/4-0/#/api/Ext.Element-method-on

If that doesn't get you going just post back and maybe include your renderer code snippet and maybe we can get an example going for you.

Thank you very much for you reply.

So at what point do I add those event handlers to the div? My grid takes a while to load. 'render' fires before that element is ready. So when I do query for the element to attach a listener, I get an empty array back. I hope I am getting what you meant!

Here is what my renderer more or less looks like:



...
columns: [
{
xtype: 'gridcolumn',
flex: 1,
text: '',
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
return '<div class="myapp-task-wrapper">' +
'<div class="myapp-task-right-controls-section">' +
'<div class="myapp-task-control-cell myapp-task-text-cell myapp-task-control-pr-cell">' +
'P' + record.get('pr') +
'</div>' +
'<div class="myapp-task-control-cell myapp-task-text-cell myapp-task-control-es-cell">' +
record.get('es') + 'H' +
'</div>' +
'<div class="myapp-task-control-cell myapp-task-control-esc-cell"></div>' +
'<div class="myapp-task-control-cell myapp-task-text-cell myapp-task-control-f-cell">' +
'F' + record.get('f') +
'</div>' +
'<div class="myapp-task-control-cell myapp-task-text-cell myapp-task-control-a-cell">' +
record.get('a') +
'</div>' +
'</div>' +
'</div>';
}
}
],
...


So I need the slider when mouseover-ed: 'myapp-task-control-esc-cell' div.

In my controller, I am doing this:



this.control({
'mygrid mygridcolumn': {
afterrender: this.onGridColumnAfterRender
}
});


and in this.onGridColumnAfterRender



var cells = gridColumn.query('.myapp-task-control-esc-cell');
// But I am getting back an empty array here.


Any ideas?

skirtle
15 Aug 2011, 6:40 PM
Using the delegate option as slemmon suggested would not only reduce memory consumption but would also work around the problems with delayed rendering. Delegating involves registering the listener on a single container element (i.e. one of the elements that surrounds the whole grid body). The delegate option then specifies a CSS selector that will be used to pick out the actual target element for the click event.

It might look something like this:


el.on('click', function() {
..
}, el, {delegate: '.myapp-task-control-esc-cell'});

Even though the listener is registered on el it will only be called if the click occurs on an element that matches the CSS selector (or one of its child elements). Further, the getTarget() method of the event object will return the matching delegate. You then just need some way of mapping from the element returned back to the row in question. That depends on what information you write into your HTML in the first place.

This gets around the rendering delay because the delegate elements don't need to exist when the listener is registered, only el needs to exist at that point.

abcdef
15 Aug 2011, 8:51 PM
Using the delegate option as slemmon suggested would not only reduce memory consumption but would also work around the problems with delayed rendering. Delegating involves registering the listener on a single container element (i.e. one of the elements that surrounds the whole grid body). The delegate option then specifies a CSS selector that will be used to pick out the actual target element for the click event.

It might look something like this:


el.on('click', function() {
..
}, el, {delegate: '.myapp-task-control-esc-cell'});

Even though the listener is registered on el it will only be called if the click occurs on an element that matches the CSS selector (or one of its child elements). Further, the getTarget() method of the event object will return the matching delegate. You then just need some way of mapping from the element returned back to the row in question. That depends on what information you write into your HTML in the first place.

This gets around the rendering delay because the delegate elements don't need to exist when the listener is registered, only el needs to exist at that point.

Oh ok! That makes sense now. Thanks...now I could find the delegate on addListener in the Docs too!