Skip to content
Melloware Home
GitHubStackOverflowLinkedIn

PrimeFaces SelectOneButton and SelectManyButton Custom Rendering

PrimeFaces, JSF, Faces5 min read

PrimeFaces 15.0.10 introduces a significant enhancement to the SelectOneButton and SelectManyButton components: support for custom rendering. This new feature enables developers to completely customize the appearance and content of button options, including the ability to add badges, icons, and other custom elements, providing greater flexibility in designing user interfaces.

What Is Custom Rendering?

Custom rendering allows you to define custom HTML structure for each button option using the custom facet. Instead of being limited to simple text labels, you can now create fully customized button layouts with any HTML elements, JSF components, or PrimeFaces components like badges. This feature provides complete control over how each option is displayed.

Custom Layout Using Facet

The most straightforward approach is to use the custom facet directly within the component. You define one custom button element for each f:selectItem, and each custom button must have role="radio" and tabindex attributes for proper accessibility and functionality.

Here's an example that demonstrates custom rendering with color indicators and badges:

1<p:selectOneButton id="customButton" value="#{selectOneButtonView.color}">
2 <p:ajax event="change" listener="#{selectOneButtonView.onChange}" />
3
4 <f:selectItem itemLabel="Red" itemValue="Red"/>
5 <f:selectItem itemLabel="Green" itemValue="Green"/>
6 <f:selectItem itemLabel="Blue" itemValue="Blue"/>
7
8 <f:facet name="custom">
9 <div class="custom-button" role="radio" tabindex="0">
10 <span class="legend" style="background:red; display:inline-block; width:1rem; height:1rem; border-radius:0.25rem; vertical-align:middle; margin-right:0.5rem;"/> Red
11 </div>
12 <div class="custom-button" role="radio" tabindex="0">
13 <span class="legend" style="background:green; display:inline-block; width:1rem; height:1rem; border-radius:0.25rem; vertical-align:middle; margin-right:0.5rem;"/> Green
14 </div>
15 <p:badge icon="pi pi-bell" severity="info" iconPos="left">
16 <div class="custom-button" role="radio" tabindex="0">
17 <span class="legend" style="background:blue; display:inline-block; width:1rem; height:1rem; border-radius:0.25rem; vertical-align:middle; margin-right:0.5rem;"/> Blue
18 </div>
19 </p:badge>
20 </f:facet>
21</p:selectOneButton>

In this example, each button option displays a colored legend indicator along with its label. The third option (Blue) is wrapped in a p:badge component to demonstrate how badges can be integrated with custom rendering.

Custom Layout Using Referenced Elements

For more complex layouts or when you need to separate the button definitions from the component, you can use the layout="custom" attribute and define the custom buttons outside the component. The buttons are matched to the f:selectItem elements by their order.

Here's an example demonstrating a payment method selector with icons and detailed information:

1<div id="customButton2Container">
2 <p:selectOneButton id="customButton2" value="#{selectOneButtonView.paymentMethod}" layout="custom">
3 <p:ajax event="change" listener="#{selectOneButtonView.onChange}" />
4
5 <f:selectItem itemLabel="PayPal" itemValue="PayPal"/>
6 <f:selectItem itemLabel="Bitcoin" itemValue="Bitcoin"/>
7 <f:selectItem itemLabel="Credit Card" itemValue="Credit Card" itemDisabled="true"/>
8 <f:selectItem itemLabel="Cash" itemValue="Cash"/>
9 </p:selectOneButton>
10
11 <div class="flex flex-wrap justify-content-start mt-3">
12 <div class="payment-button paypal" role="radio" tabindex="0">
13 <i class="pi pi-paypal payment-icon"></i>
14 <div class="payment-title">PayPal</div>
15 <div class="payment-tagline">Secure online payment</div>
16 </div>
17 <div class="payment-button bitcoin" role="radio" tabindex="0">
18 <i class="pi pi-bitcoin payment-icon"></i>
19 <div class="payment-title">Bitcoin</div>
20 <div class="payment-tagline">Cryptocurrency payment</div>
21 </div>
22 <div class="payment-button creditcard ui-state-disabled" role="radio" tabindex="-1">
23 <i class="pi pi-credit-card payment-icon"></i>
24 <div class="payment-title">Credit Card</div>
25 <div class="payment-tagline">Currently unavailable</div>
26 </div>
27 <div class="payment-button cash" role="radio" tabindex="0">
28 <i class="pi pi-money-bill payment-icon"></i>
29 <div class="payment-title">Cash</div>
30 <div class="payment-tagline">Pay on delivery</div>
31 </div>
32 </div>
33</div>

This approach allows for more complex layouts with multiple elements per button, such as icons, titles, and taglines. Note that disabled items should have tabindex="-1" and the ui-state-disabled class.

Key Requirements for Custom Rendering

When implementing custom rendering, keep these requirements in mind:

  1. One custom button per selectItem: Each f:selectItem must have a corresponding custom button element in the custom facet or in the referenced container.

  2. Required attributes: Each custom button must have:

    • role="radio" for accessibility
    • tabindex="0" for enabled items (or tabindex="-1" for disabled items)
  3. Order matters: The order of custom buttons must match the order of f:selectItem elements.

  4. Badge integration: Badges can wrap custom button elements or be included within them, as shown in the first example.

SelectManyButton with Custom Rendering

The SelectManyButton component supports the same custom rendering features. You can use either the custom facet or the layout="custom" approach:

1<p:selectManyButton value="#{bean.selectedOptions}">
2 <f:selectItem itemLabel="Option A" itemValue="A" />
3 <f:selectItem itemLabel="Option B" itemValue="B" />
4 <f:selectItem itemLabel="Option C" itemValue="C" />
5
6 <f:facet name="custom">
7 <div class="custom-button" role="checkbox" tabindex="0">
8 <p:badge value="3" severity="success" />
9 <span>Option A</span>
10 </div>
11 <div class="custom-button" role="checkbox" tabindex="0">
12 <p:badge value="5" severity="warning" />
13 <span>Option B</span>
14 </div>
15 <div class="custom-button" role="checkbox" tabindex="0">
16 <span>Option C</span>
17 </div>
18 </f:facet>
19</p:selectManyButton>

Note that for SelectManyButton, the role should be "checkbox" instead of "radio".

Backing Bean Example

Here's a simple backing bean that can support custom rendering:

1@Named
2@ViewScoped
3public class SelectOneButtonView implements Serializable {
4 private String color;
5 private String paymentMethod;
6
7 public void onChange(AjaxBehaviorEvent event) {
8 // Handle the change event
9 // You can access the component and perform any necessary logic
10 }
11
12 // Getters and setters
13 public String getColor() {
14 return color;
15 }
16
17 public void setColor(String color) {
18 this.color = color;
19 }
20
21 public String getPaymentMethod() {
22 return paymentMethod;
23 }
24
25 public void setPaymentMethod(String paymentMethod) {
26 this.paymentMethod = paymentMethod;
27 }
28}

Benefits

The addition of custom rendering to SelectOneButton and SelectManyButton provides several advantages:

  • Complete Design Control: Create fully customized button layouts that match your application's design requirements and branding.
  • Badge Support: Adding badges to buttons, a frequently requested feature, is now possible through custom rendering. Display counts, status indicators, or any other contextual information.
  • Rich Content: Include icons, images, multiple text elements, or any other HTML/JSF components within button options.
  • Improved User Experience: Provide users with more context and visual cues directly within the button options, making interfaces more intuitive and engaging.
  • Flexible Layouts: Choose between inline facet-based rendering or referenced external layouts depending on your needs.

Conclusion

The custom rendering feature in PrimeFaces 15.0.10 makes SelectOneButton and SelectManyButton more powerful and flexible components. By leveraging the custom facet or layout="custom" attribute, developers can create visually rich and informative user interfaces that go far beyond simple text labels. Whether you need to add badges, icons, complex layouts, or other custom content, custom rendering provides the flexibility to tailor these components to your specific needs.

For more detailed information and additional configuration options, refer to the official PrimeFaces documentation:

  • SelectOneButton
  • SelectManyButton
© 2025 by Melloware. All rights reserved.