Wednesday, July 29, 2009

DataGridColumn header tooltips

I really thought that something as simple as putting a tooltip on a DataGridColumn header would be easy to do in Flex.

If you want to make your own headerRenderer, then it is obviously very simple to just set the toolTip property in your renderer. But I was curious if it could easily be done with out a custom header renderer. My solution was to create a new class which extended DataGridColumn and adds three new properties: headerToolTip, headerToolTipPosition, and headerTextTruncate (which adds the "..." if the headerText is too long to fit).

Here is the simplified version of the MXML code:
<mx:DataGrid x="10" y="10" width="500" height="130" dataProvider="{employees}">
    <ui:DataGridToolTipColumn headerText="Phone" dataField="phone" width="90"
      headerToolTip="Phone Number (tooltip above)" headerToolTipPosition="above"/>

The headerToolTipPosition property can have the following values:
  • above - positions the tooltip above the header
  • below - positions the tooltip below the header
  • left - positions the tooltip to the left of the header
  • right - positions the tooltip to the right of the header
  • inline - positions the tooltip on top of the header
  • default - positions the tooltip slightly below and to the right of the header (this is the default value if headerToolTipPosition isn't specified.

  • And here is the example (right-click View Source for the full source code):

    Feel free to use this code or modify it to your own needs.

    ** Updated on September 16th 2009
  • Fixed it so that setting headerWordWrap="true" now works as expected.
  • When the headerToolTip isn't defined then no tooltip is shown.
  • Added a new property: headerTextTruncate which will truncate the headerText and add the ellipsis ("...") if the headerText doesn't fit inside the renderer. Note that this property doesn't work if the headerWordWrap property is set to true.


    mario said...

    Nice one, it seems to work really well! Trying this out I notice that a couple minor things:

    First, that it seems to ignore headerWordWrap=true on the DGC. This is actually not really a problem given that in this case we have the convenience of a tooltip to anyhow be able to show all the text.

    Secondly, when no headerToolTip is defined on the DGC, it seems that you use the header text as default tooltip text. If in some cases we wish to explicitly not have a tooltip show up, it seems we'd need to explicitly set headerToolTip="" (i.e. to empty string) ?

    Chris Callendar said...

    Thanks for the comment Mario.
    I've fixed the code above to work as you expected - the headerWordWrap now works, and if the headerToolTip is not defined then no tooltip is shown.

    mario said...

    I downloaded your updated zip... perfect, thanks! They are really minor nitpicks, but they do make this component even neater. (Note, doing View Source on the inlined swf still gives the old source). Thanks again... mario
    ps: I see you are a big runner & live in sunny Victoria! Incidentally, I'll be running the Fyne Nature Marathon (Yverdon to Neuch√Ętel, Suisse) this sunday & I used to live in Van City... ;-!

    Chris Callendar said...

    Hey Mario,

    I think the View Source is up to date now, thanks.

    Sadly I'm not running much these days due to a knee injury. I'm dying to get back out there and run another marathon (I've only done one - the Royal Victoria), but that will have to wait until next year... Best of luck on Sunday! Looks like a fun marathon.


    JT said...

    I just tried the latest code and it works great!

    I did notice that if you truncate the text and then resize the column you get a ToolTipManager exception (when using the Flash Debug 10 plugin).

    <ui:DataGridToolTipColumn headerText="Date Shipped" dataField="dateshipped" headerToolTip="Date Shipped" headerTextTruncate="true" headerToolTipPosition="above"/>

    Is this something other people have eperienced?

    Chris Callendar said...

    Hi JT,
    I certainly haven't seen any errors, and I tried using your code too and no problems. Does it give you a stack trace when you get the error? I'd be curious to see it.

    JT said...

    It turns out that the issue I was receiving was because I was using the Flex SDK 3.2.0 and not the latest SDK 3.4.0 - which seems to have resolved the issue.

    Chris Callendar said...

    Good to know JT, thanks for posting.

    Anonymous said...

    This is cool! This code worked great for me. Thanks!

    Brendan M said...

    Great component... thanks!

    Nicolas said...

    Didn't like my itemRenderer


    But then I realised that I forgot the to change the prefix from 'mx' to 'ui' Doh! : )

    Great script mate thanks for sharing!

    Anonymous said...

    I need to sort a column as numeric. I've tried a couple of ways but doesn't work with ui:DataGridToolTipColumn... sortCompareFunction="myCompareFunc", any ideas

    Chris Callendar said...

    To sort a column as numeric, try this:

    <mx:DataGridColumn dataField="num" headerText="Number"

    sort function:
    private function sortNumbers(a:Object, b:Object):int {
    return ObjectUtil.numericCompare(a.num, b.num);

    If you want the data initially sorted, you can sort like this.
    Array (smallest numbers first)
    or to put biggest numbers first:
    array.sort(Array.NUMERIC | Array.DESCENDING);

    ArrayCollection (sorting on the "num" property):
    ac.sort = new Sort();
    ac.sort.fields = [new SortField("num", false, false, true)];

    Bean said...

    Cheers dude, very handy!

    Josh Stafford said...

    One question--why are you overriding a headerRenderer with an itemRenderer? I was overriding the headerRenderer already to add background colors, and now this is gunking up the works.

    Chris Callendar said...

    The headerRenderer is what actually displays the tooltip, so it is required if you want a tooltip on the header! It also controls the positioning of the tooltip (above, below, etc).

    You should be able to merge my HeaderRenderer helper class with your existing header renderer to get the combined functionality. You can right click view source on the example above, and look inside the file.

    Anonymous said...

    This is excellent post. I tried it and it worked like charm for datagrid. However, I need similar implmentation for advancedDataGrid. I tried replacing Datagrid and DatagridColumn class with AdvancedDatagrid counterparts; however it didn't work. I would be great help if you have working implementation for advancedDatagrid