PDA

View Full Version : Grid cell tooltip



webdev2111
6 Feb 2012, 10:22 AM
I have been searching everywhere for a solution to using quicktip/tooltip on how to add tooltip to each gridcell and it doesnt seem to be working..



What I am trying to do is have a mouse over on a cell I want a t tooltip to show with the value in the cell

Anyone have any suggestions how I can add extjs tooltip to this?


var listView = Ext.create('Ext.grid.Panel', {
store: mystore,
multiSelect: true,
viewConfig: {
emptyText: 'No images to display'
},
//reserveScrollOffset: true,
renderTo: containerEl,

columns: [
{
text: 'Class',
flex: 10,
dataIndex: 'ClassName',
renderer: function(value, metaData, record) {
return Ext.String.format('<a href="#" class="tooltip2">{0}<span>{0}</span></a>', value);
}

]
});

mitchellsimoens
6 Feb 2012, 11:45 AM
Moved to the Ext JS 4 Q&A forum and wrapped your code with [CODE] tags.

In Ext JS 4, the attribute you should use is 'data-qtip'

webdev2111
8 Feb 2012, 8:48 AM
How can I go about adding the data-qtip on the code?
I like the anchor and mousetrackign and the ba sic tooltps
http://www.extjs.com/examples/explorer.html#tooltips

Thanks

Moved to the Ext JS 4 Q&A forum and wrapped your code with [CODE] tags.

In Ext JS 4, the attribute you should use is 'data-qtip'

charris
24 Feb 2012, 4:55 AM
You can configure your column to use a renderer that, in addition to returning the value shown in the cell, can modify the <td> element surrounding the cell. Specifically, you can add the "data-qtip" attribute, which will cause ExtJS to display a tooltip when the mouse rolls over the <td> (e.g., <td ... data-qtip="Here's the tooltip">). The column config might look like this:

{
text: 'Column Header Blah',
dataIndex: 'blah',
renderer: function(value, metaData, record, rowIdx, colIdx, store) {
metaData.tdAttr = 'data-qtip="' + value + '"';
return value;
}
}
Make sure to HTML encode the cell value and data-qutip value (twice) if your data needs it:

{
renderer: function(value, metaData, record, rowIdx, colIdx, store) {
// Sample value: msimms & Co. "like" putting <code> tags around your code

value = Ext.String.htmlEncode(value);

// "double-encode" before adding it as a data-qtip attribute
metaData.tdAttr = 'data-qtip="' + Ext.String.htmlEncode(value) + '"';

return value;
}
}

WBX
28 Nov 2012, 1:00 PM
Thanks Clint and Mitchell for the tips (no pun intended) on this. This post should probably be marked as answered.

Clint, could you explain the need to double encode the value?

Also, I discovered that this strategy doesn't work well with the Ext.grid.column.Column convenience subclasses as it overrides the defaultRenderer for those classes. I made a post asking about this: http://www.sencha.com/forum/showthread.php?250145-Grid-cell-tooltips-for-Ext.grid.column.*-columns

Do either of you have any ideas of how to address this?

Thanks
Gary

slemmon
28 Nov 2012, 1:34 PM
Not sure how long you can count on this code since it uses some undocumented stuff, but.... works in 4.1.3

But, this way you don't have to keep up with a renderer for each column - it'll grab the value dynamically for every column.

http://jsfiddle.net/slemmon/GEwkG/


Ext.tip.QuickTipManager.init();

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'
}
}
});

Ext.create('Ext.grid.Panel', {
title: 'Simpsons',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
columns: [
{ text: 'Name', dataIndex: 'name' },
{ text: 'Email', dataIndex: 'email', flex: 1 },
{ text: 'Phone', dataIndex: 'phone' }
],
height: 200,
width: 400,
renderTo: Ext.getBody()
, listeners: {
viewready: function (grid) {
var view = grid.view;

// record the current cellIndex
grid.mon(view, {
uievent: function (type, view, cell, recordIndex, cellIndex, e) {
grid.cellIndex = cellIndex;
grid.recordIndex = recordIndex;
}
});

grid.tip = Ext.create('Ext.tip.ToolTip', {
target: view.el,
delegate: '.x-grid-cell',
trackMouse: true,
renderTo: Ext.getBody(),
listeners: {
beforeshow: function updateTipBody(tip) {
if (!Ext.isEmpty(grid.cellIndex) && grid.cellIndex !== -1) {
header = grid.headerCt.getGridColumns()[grid.cellIndex];
tip.update(grid.getStore().getAt(grid.recordIndex).get(header.dataIndex));
}
}
}
});

}
}
});


This snippet assumes a dataIndex property for each column.

bseddon
4 Jan 2013, 1:59 PM
When using Sencha Architect it's not possible to override the 'renderer' method as it's protected. Instead you can add an event listener to intercept the 'afterLayout' event and add this code:


var store = this.getView().getStore();
var nodes = this.getView().getNodes();

Ext.Array.forEach(nodes, function(tr, i)
{
var record = store.getAt(i);
if ( record.data.qtip === undefined) return;

var el = Ext.get(tr);
el.set({'data-qtip': record.data.qtip});
});

This example assumes your record has a field 'qtip' but of course you can use any field or combination or mechanism to compute the tip you want.

If you are using the cell editor plug-in, add a listener to the 'edit' event of the plug-in and in the event update the qtip (or other field(s) you are using) with the consequences of the edit.

joshua.ball@osi.com
5 Feb 2013, 5:44 PM
This is a function I call (among others) from the 'viewready' event of the main grid panel:


initToolTip: function(){
var view = this.view.getView();
this.toolTip = Ext.create('Ext.tip.ToolTip', {
target: view.el,
delegate: view.cellSelector,
trackMouse: true,
renderTo: Ext.getBody(),
listeners: {
beforeshow: function(tip) {
var trigger = tip.triggerElement,
parent = tip.triggerElement.parentElement,
columnTitle = view.getHeaderByCell(trigger).text,
columnDataIndex = view.getHeaderByCell(trigger).dataIndex,
columnText = view.getRecord(parent).get(columnDataIndex).toString();
if (columnText){
tip.update("<b>" + columnTitle + ":</b> " + columnText);
} else {
return false;
}
}
}
});

This only utilizes the private method 'getHeaderByCell' of the Ext.grid.View object. Fair compromise. I'd love for something like this to be fully supported by the framework, though.

jimmylu98
21 May 2014, 9:53 AM
Thanks, this works with 4.2.2. http://jsfiddle.net/slemmon/GEwkG/ is not work any more with 4.2.2.


This is a function I call (among others) from the 'viewready' event of the main grid panel:


initToolTip: function(){
var view = this.view.getView();
this.toolTip = Ext.create('Ext.tip.ToolTip', {
target: view.el,
delegate: view.cellSelector,
trackMouse: true,
renderTo: Ext.getBody(),
listeners: {
beforeshow: function(tip) {
var trigger = tip.triggerElement,
parent = tip.triggerElement.parentElement,
columnTitle = view.getHeaderByCell(trigger).text,
columnDataIndex = view.getHeaderByCell(trigger).dataIndex,
columnText = view.getRecord(parent).get(columnDataIndex).toString();
if (columnText){
tip.update("<b>" + columnTitle + ":</b> " + columnText);
} else {
return false;
}
}
}
});

This only utilizes the private method 'getHeaderByCell' of the Ext.grid.View object. Fair compromise. I'd love for something like this to be fully supported by the framework, though.

worthlutz
22 Sep 2014, 10:08 AM
All these methods of adding a tooltip to a cell seem to fall apart when locking columns. Apparently locked columns splits the grid up into two grids, locked and normal.

With a locked column or two, the "viewready" event is never caught so the methods described above do not work.


So many options and I cannot get them to work together. :(


Can anyone point me in the right direction to attempt a fix which will work with locked columns?

EDIT:

My solution was to setup a listener for "viewready" on both grids contained in the lockable grid if they existed. My solution may not cover every possibility but it seem to be working.

I did it like this in my plugin:



init: function (grid) {
var me = this,
grids = [grid],
i,ii;

if (grid.lockedGrid) {
grids[0] = grid.lockedGrid;
grids[1] = grid.normalGrid;
}

for (i = 0, ii = grids.length; i < ii; i++) {
grid.mon(grids[i], {
viewready: me.onViewReady,
scope: me
});
}
}


I'd like to hear if you see any obvious problems with this. Also if they are not obvious. :)


Worth