I'd like to customize the default layout of <h:selectOneRadio>
.
In my case, I need to put a <h:selectManyCheckbox>
after every radio button. This is what I have so far:
<h:selectOneRadio value="#{user.Request}">
<f:selectItem itemValue="Request1" itemLabel="Request1" />
<f:selectItem itemValue="Request2" itemLabel="Request2" />
</h:selectOneRadio>
<h:selectManyCheckbox value="#{user.Request1}">
<f:selectItem itemValue="Certificate1" itemLabel="Certificate1" />
<f:selectItem itemValue="Certificate2" itemLabel="Certificate2" />
</h:selectManyCheckbox>
<h:selectManyCheckbox value="#{user.Request2}">
<f:selectItem itemValue="Certificate3" itemLabel="Certificate3" />
<f:selectItem itemValue="Certificate4" itemLabel="Certificate4" />
</h:selectManyCheckbox>
I tried to put them after each select item:
<h:selectOneRadio value="#{user.Request}">
<f:selectItem itemValue="Request1" itemLabel="Request1" />
<h:selectManyCheckbox value="#{user.Request1}">
<f:selectItem itemValue="Certificate1" itemLabel="Certificate1" />
<f:selectItem itemValue="Certificate2" itemLabel="Certificate2" />
</h:selectManyCheckbox>
<f:selectItem itemValue="Request2" itemLabel="Request2" />
<h:selectManyCheckbox value="#{user.Request2}">
<f:selectItem itemValue="Certificate3" itemLabel="Certificate3" />
<f:selectItem itemValue="Certificate4" itemLabel="Certificate4" />
</h:selectManyCheckbox>
</h:selectOneRadio>
But it didn't work. What is the proper way to do this?
This markup is not supported by standard JSF <h:selectOneRadio>
.
There are JSF component libraries offering a more flexible component, such as Tomahawk with <t:selectOneRadio layout="spread"><t:radio>
:
<html ... xmlns:t="http://myfaces.apache.org/tomahawk">
<!-- This one won't display anything. -->
<t:selectOneRadio id="request" value="#{user.request}" layout="spread">
<f:selectItem itemValue="#{1}" itemLabel="Request 1" />
<f:selectItem itemValue="#{2}" itemLabel="Request 2" />
<f:ajax render="requests" />
</t:selectOneRadio>
<!-- Just markup them the way you want! -->
<h:panelGroup id="requests" layout="block">
<ul>
<li>
<t:radio for="request" index="0" />
<h:selectManyCheckbox value="#{user.request1}" disabled="#{user.request != 1}">
...
</h:selectManyCheckbox>
</li>
<li>
<t:radio for="request" index="1" />
<h:selectManyCheckbox value="#{user.request2}" disabled="#{user.request != 2}">
...
</h:selectManyCheckbox>
</li>
</ul>
</h:panelGroup>
PrimeFaces has a similar component, the <p:selectOneRadio layout="custom"><p:radioButton>
:
<html ... xmlns:p="http://primefaces.org/ui">
<!-- This one won't display anything. -->
<p:selectOneRadio id="request" value="#{user.request}" layout="custom">
<f:selectItem itemValue="#{1}" itemLabel="Request 1" />
<f:selectItem itemValue="#{2}" itemLabel="Request 2" />
<p:ajax update="requests" />
</p:selectOneRadio>
<!-- Just markup them the way you want! -->
<h:panelGroup id="requests" layout="block">
<ul>
<li>
<p:radioButton for="request" itemIndex="0" />
<h:selectManyCheckbox value="#{user.request1}" disabled="#{user.request != 1}">
...
</h:selectManyCheckbox>
</li>
<li>
<p:radioButton for="request" itemIndex="1" />
<h:selectManyCheckbox value="#{user.request2}" disabled="#{user.request != 2}">
...
</h:selectManyCheckbox>
</li>
</ul>
</h:panelGroup>
Either way, just let disabled
attribute of the checkbox group check the currently selected radio button value (which I've for simplicitly changed to a Long
, but an enum
would probably be more self-documenting), and use the usual ajax magic to partially update the view during change event.
If reusing an enhanced component from an existing JSF component library is not an option for some reason, then you'd need to write all by yourself. Most simplest would be overriding the standard <h:selectOneRadio>
renderer to recognize a new layout
attribute and then generate the desired HTML output accordingly like abovementioned components to. See also a.o. How to override h:selectOneRadio renderer? Where is the renderer class in jsf-impl?