The White Blog

A blog for technology, life, and food

  • Home
  • Photos
  • About
  • General
  • Life & Family
  • Programming
  • Gadgets & Toys
  • Food
  • Pictures

    • The White Pets
    • Western Carribean
    • Eastern Carribean
    • St. Louis
  • Other Pages

    • Side Projects
    • GeoCaching
    • Andrew's Wishlist
    • Christina's Wishlist
  • Across the Web

    View Andrew White's profile on LinkedIn profile for Andrew White on Stack Exchange, a network of free, community-driven Q&A sites
  • Gallery

    DSC00246           DSC00511
  • Recent Posts

    • Remembering Merlin
    • Returning and Accepting Interfaces with CXF/JAX-WS
    • LEGO Dice Tower
    • Truthfulness of the 2012 Presidential Political Candidates
    • Slider Solver for Klotski Puzzles
  • Older Posts

    • March 2013 (1)
    • June 2012 (1)
    • May 2012 (1)
    • March 2012 (2)
    • February 2012 (1)
    • January 2012 (2)
    • March 2011 (2)
    • November 2010 (2)
    • September 2010 (2)
    • July 2010 (1)
    • June 2010 (3)
    • May 2010 (5)
    • April 2010 (4)
    • March 2010 (6)
    • February 2010 (1)
    • January 2010 (1)
    • December 2009 (1)
    • November 2009 (1)
    • September 2009 (1)
    • August 2009 (1)
    • July 2009 (2)
    • May 2009 (2)
    • March 2009 (2)
    • February 2009 (1)
    • January 2009 (1)
    • November 2008 (1)
    • October 2008 (1)
    • September 2008 (2)
    • August 2008 (1)
    • July 2008 (1)
    • June 2008 (2)
    • April 2008 (2)
    • February 2008 (2)
    • January 2008 (1)
    • December 2007 (3)
    • November 2007 (2)
    • October 2007 (2)
    • September 2007 (1)
    • August 2007 (6)
    • July 2007 (8)
    • June 2007 (7)
  • Site Tools

    • Log in
    • Entries RSS
    • Comments RSS
    • WordPress.org
  • Switch site

    • Switch to our mobile site

ICEFaces Tooltip and Data Table

Update: If you simply need to have a single tolltip for a single ice:column then simply include the tooltip along side the body like normal. If you need to reference a dynamic tooltip from multiple columns or if the tooltip needs to be external to the datatable, please keep reading

Making a panelToolTip work with a dataTable in ICEFaces can be non-trivial. The lack of good examples doesn’t help either. In this example we will show a table of “Things” that each have three fields. The table will only show fieldA and fieldB while the tooltip will show fieldC. Note that we treat fieldA like a key, i.e. it is unique among the items.

First let us define our Thing class as an inner static class to a backing bean like so…

static public class Thing {
	private String fieldA;
	private String fieldB;
	private String fieldC;
 
	public Thing(String fieldA, String fieldB, String fieldC) {
		super();
		this.fieldA = fieldA;
		this.fieldB = fieldB;
		this.fieldC = fieldC;
	}
        /* getters */
}

Next let’s define the dataTable which will show our array of Things, but it only shows field A and B…

<ice:dataTable value="#{tooltipTableExample.things}"
               var="thing" >
    <h:column>
        <f:facet name="header">
            <ice:outputText value=""/>
        </f:facet>
        <ice:panelGroup panelTooltip=":::thingPanelToolTip">
            <ice:outputText value="hover"/>
            <ice:outputText id="hoverID"
                            style="display: none"
                            value="#{thing.fieldA}" />
        </ice:panelGroup>
    </h:column>
    <h:column>
        <f:facet name="header">
            <ice:outputText value="Field A"/>
        </f:facet>
        <ice:outputText value="#{thing.fieldA}"/>
    </h:column>
    <h:column>
        <f:facet name="header">
            <ice:outputText value="Field B"/>
        </f:facet>
        <ice:outputText value="#{thing.fieldB}"/>
    </h:column>
</ice:dataTable>

This is a standard dataTable with two key exceptions, both in the first column.

  1. The use of panelTooltip=”:::thingPanelToolTip”
  2. The use of an invisible outputText

Note that the panelTooltip does not appear in the dataTable. This is because the dataTable works on lists of data and the panelTooltip does not. That is, JSF would have a hard time figuring out which tooltip to use if the tooltip appeared in the dataTable since there would be one for each row.

Quick Tip: the :::Name syntax is used to tell JSF to look up the XML tree until it finds an ID that matches instead of just the current scope.

Next,  define what the tooltip looks like…

<ice:panelTooltip id="thingPanelToolTip"
                  displayListener="#{tooltipTableExample.tooltipDisplayListener}">
    <f:facet name="header">
        <ice:panelGroup>
           <ice:outputText value="Field C"/>
        </ice:panelGroup>
    </f:facet>
    <f:facet name="body">
       <ice:panelGroup>
            <ice:outputText value="#{tooltipTableExample.hoveredThing.fieldC}"/>
       </ice:panelGroup>
    </f:facet>
</ice:panelTooltip>

Nothing too special here, but note the use of a display listener. The display listener gives the server a chance to figure out which Thing is being hovered.

Finally, the backing bean…

public class TooltipTableExample {
	/* things => "things" that the dataTable will show
	 * fieldAtoStringMap => maps field A to a thing
	 * hoverThingFieldA => the filed A of the hovered thing
	 */
	private Thing[]              things;
	private Map   fieldAtoStringMap;
	private String               hoverThingFieldA;
 
	public TooltipTableExample() {
		things = new Thing[] {
					new Thing("1", "A", "X"),
					new Thing("2", "B", "Y"),
					new Thing("3", "C", "Z") };
 
		/* build our map of fieldA => thing */
		fieldAtoStringMap = new HashMap();
		for (Thing t : things) {
			fieldAtoStringMap.put(t.getFieldA(), t);
		}
	}
 
	/* when the tooltip appears, this will get called */
	public void tooltipDisplayListener(DisplayEvent event) {
		if (event.isVisible() == false) {
			/* if hiding tooltip do nothing */
			return;
		}
 
		/* target is the component that is being hovered; in this
		 * case, it's a panelGroup in the datatable
		 */
		for (UIComponent child : event.getTarget().getChildren()) {
			/* if the child's id matches our hard coded "holder" id
			 * then set the current hover field A to it's value
			 */
			if (   child.getId().equals("hoverID") == true
				&& child instanceof HtmlOutputText) {
 
				HtmlOutputText hot = (HtmlOutputText) child;
				this.setHoverThingFieldA(hot.getValue().toString());
				return;
			}
		}
	}
 
        public Thing getHoveredThing() {
            return this.getFieldAtoStringMap().get(this.getHoverThingFieldA());
        }
	/* getters and Thing class */

Most of the interesting stuff happens in the display listener, and the comments in the code are pretty good documentation. In short, this backing bean has an array of Things, a map of keys to things, and the ID of the currently hovered thing. The display listener will look for the hidden output text in the row and use that to set the currently selected thing.

I am sure there are better ways, but this is the simplest method I could come up with after searching the web for hours.

Feb 20, 2010aewhiteCategory: General, Programming Read more Comments (4)
Tags: ICEFaces, Java

© 2008 The White Blog | Create by: Tatoon | Valid XHTML | CSS