9
votes

I would like to add a tooltip for each element in a p:selectManyCheckBox. However I can't come up with a solution.

I've got a class Role that has 3 properties, "id" (Long), "name" (String) and "description" (String). The name is displayed and I would like to have the description as a tooltip.

This is a working piece of code:

<p:selectManyCheckbox layout="pageDirection" value="#{roleBean.selectedRoles}" converter="roleConverter">
    <f:selectItems value="#{roleBean.roles}" var="role" itemLabel="#{role.name}" itemValue="#{role}"/>
</p:selectManyCheckbox>

The roleConverter is a FacesConverter that converts the Role to an id and visa versa.

I came up with this:

<p:selectManyCheckbox layout="pageDirection" value="#{roleBean.selectedRoles}" converter="roleConverter">
    <c:forEach var="role" items="#{roleBean.roles}">
        <f:selectItem id="role#{role.id}" itemLabel="#{role.name}" itemValue="#{role}" />
        <p:tooltip for="role#{role.id}" value="#{role.description}"/>
    </c:forEach>
</p:selectManyCheckbox>

But unfortunately it doesn't work.

3

3 Answers

16
votes

You can achieve this by using the SelectItem#getDescription() property as below:

<p:selectManyCheckbox layout="pageDirection"
    value="#{roleBean.selectedRoles}" converter="roleConverter">
    <f:selectItems value="#{roleBean.roles}" var="role" 
        itemValue="#{role}" itemLabel="#{role.name}" 
        itemDescription="#{role.description}" />
</p:selectManyCheckbox>

This is supported since PrimeFaces 6.2 (actually because of this very answer you're reading now).

In case you're not on PrimeFaces 6.2 yet and cannot upgrade for some reason, then you need to manually override the PrimeFaces SelectManyCheckboxRenderer#encodeOptionLabel() as below in order to recognize and render it:

public class YourSelectManyCheckboxRenderer extends SelectManyCheckboxRenderer {

    @Override
    protected void encodeOptionLabel(FacesContext context, SelectManyCheckbox checkbox, String containerClientId, SelectItem option, boolean disabled) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("label", null);
        writer.writeAttribute("for", containerClientId, null);

        if (option.getDescription() != null) {
            writer.writeAttribute("title", option.getDescription(), null);
        }

        if (disabled) {
            writer.writeAttribute("class", "ui-state-disabled", null);
        }

        if (option.isEscape()) {
            writer.writeText(option.getLabel(), null);
        } else {
            writer.write(option.getLabel());
        }

        writer.endElement("label");
    }

}

Which is registered as follows in faces-config.xml:

<render-kit>
    <renderer>
        <component-family>org.primefaces.component</component-family>
        <renderer-type>org.primefaces.component.SelectManyCheckboxRenderer</renderer-type>
        <renderer-class>com.example.YourSelectManyCheckboxRenderer</renderer-class>
    </renderer>
</render-kit>
1
votes

Tooltip support for selectManyCheckbox was added since Primefaces v6.2 version. Other components support this too.

XHTML code is the same BalusC reported

<p:selectManyCheckbox layout="pageDirection" value="#{roleBean.selectedRoles}" converter="roleConverter">
    <f:selectItems value="#{roleBean.roles}" var="role" 
        itemValue="#{role}" itemLabel="#{role.name}" itemDescription="#{role.description}" />
</p:selectManyCheckbox>

but is not anymore required override the PrimeFaces SelectManyCheckboxRenderer

0
votes

I had to modify BalusC's solution to make it work in my case. That is beacause I had to build the List of SelectItems on the Bean-side.

public List<SelectItem> getMyItems(){
  List<SelectItem> mySelectItems = new ArrayList<>();
  [loop or ohter code to collect items]
  // create SelectItem with description
  mySelectItems.add(new SelectItem([value], [label], [description]));
  ...
  return mySelectItems;
}

Then these SelectItems can be used with:

<f:selectItems value="#{myBean.myItems}"/>