First, it's ludicrous that something this simple in HTML or JSP is so hard to do in JSF. These added layers should be making life easier, not harder. But it seems to me they just make life harder. I used to like them. Now I am a Java Luddite, advocating now in favor of simpler approaches that include less in the way of "new cool-sounding 'technologies'" and more in the way of "stuff that just plain works without having to struggle all week to do something that used to take just 5 minutes". Anyway, I have tried the past 3 working days to get the simple functionality in JSF to work that causes other radio buttons to deselect and leave the user-selected one unchanged. I tried several approaches including a custom tag library ("overkill", defined) and a number of mixing and matching of stuff that only produced a lot of stacktraces. I finally fell back on Javascript and accepted that creating a reliably generalized solution was not likely. I have read similar complaints elsewhere. OK, my gripe session is over. Here's what I did to slay my particular JSF-radio-button dragon:
On the .xhtml page:
<ui:composition template="../template.xhtml"
...
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"
...
>
<a4j:loadScript src="/resources/scripts/custom.js" />
...
<ui:param name="pageBean" value="#{recordsBean}" />
...
<h:dataTable id="tblMine"
value="#{pageBean.records}"
var="item"
border="1" celpadding="0" cellspacing="0"
style="font-size=10px;text-align: center;"
>
<h:column>
<f:facet name="header">
<h:panelGroup><h:panelGrid cellspacing="0" cellpadding="0" border="0"
id="rowSelect" columns="1" width="100%"><h:outputText
value="Select" /></h:panelGrid></h:panelGroup>
</f:facet>
<h:selectOneRadio id="userselectedrecord"
onclick="javascript:clearOtherRadioButtons(event);" >
<f:selectItem itemValue="#{item.recordid}"
itemLabel="" /> <!-- I set itemLabel to "" because in my case,
I don't want any text next to the radio btns -->
</h:selectOneRadio>
</h:column>
...
... and the rest of the page ...
In the custom.js file, I have:
function clearOtherRadioButtons(evnt)
{
// Have to try 'currentTarget', then 'srcElement'. Issue is Firefox
// supports 'currentTarget' but IE does not. IE supports 'srcElement'.
var btn = (evnt.currentTarget) ? evnt.currentTarget : evnt.srcElement;
var matchindexlocn = btn.id.indexOf('userselectedrecord');
var btnidstarttxt = btn.id.substring(0,
matchindexlocn + 18 ); // 'userselectedrecord' length = 18
var elementid = '';
var i = 0;
var ele = null;
var allElements = document.getElementsByTagName('*');
for(i = 0; i < allElements.length; i++)
{
elementid = allElements[i].id;
if ( (elementid.indexOf(btnidstarttxt) == -1) &&
(elementid.indexOf('_') > -1) )
{
try
{
ele = document.getElementById(elementid);
ele.checked = false;
} catch (e) {}
}
}
} // function clearOtherRadioButtons(evnt)
That's it. By way of some explanation re that if() in the Javascript:
elementid.indexOf(btnidstarttxt) == -1
--> This narrows the elements down to those that do not start with the JSF-added object ID text that is associated with the button group associated with the passed-in event. We do not want to unselect the button in the button group whose event was passed into the function.
elementid.indexOf('_') > -1
--> This narrows the elements down further to only actual buttons since JSF adds underscores to the button element IDs.
The reason the code that sets checked = false is in a try..catch block is just in case something goes wrong with any presumptions around the logic and the circumstance is not handled. If you know the environment and can control the element ids, you should be fine. However on the off chance that something changes due to, let's say for example, the app's host server getting some new version JSF library installed that overrides your app's classloading policy (in a work environment, these things as we know can happen beyond our control) that now assigns these element ids differently, the app won't break with a sudden nasty Javascript error or worse yet, the radio button selection just stops working. Worst I guess that can happen is that multiple radio btns can be selected at the same time and the user can submit them. I suppose a good precaution to take is to add yet more Javascript code to validate that only one option is being submitted by the user, or validate the user's submission server-side.
See, way too much work just to manage radio button state.