views:

42

answers:

2

I need to port an application from PHP to JSF 2. Everything is fine except for a rather complex radio button group:

alt text

When 'Process Application for:' is selected, the child radio button group is enabled. Within that, when 'Other' is selected, the corresponding text box is enabled. When 'Brands' is selected, those two text boxes are enabled. Of course, deselecting any of these disables the corresponding tags again.

I can't think of any way to do this, beyond 3 separate <h:selectOneRadioButton /> tags, with a ton of javascript handling disabling / enabling of tags, and more javascript handling selecting / deselecting across the different radio buttons so that they appear to be a single group of radio buttons. Can anyone think of a better solution than this? Something like a custom <h:selectItem />?

Thanks

A: 

For starters, apparently you can't disable radios with css. I would

  • get an array of 'process' children radios
  • get an array of 'brands' children inputs
  • set onclick events for process and brands
  • for each onclick event, disable all objects in one array, enable all objects in the other

Probably...20 lines of code, medium/worst case.

Steve
This is about as simple as you describe using straight HTML / javascript. It's not nearly as simple using JSF.
Zack
+1  A: 

Your best bet is Tomahawk's <t:selectOneRadio> with layout attribute set to spread. This has the added advantage that you will be able to position the individual radio buttons in the HTML markup the way you want using <t:radio>, as opposed to the standard <h:selectOneRadio> which only supports the layout attributes pageDirection and lineDirection and renders a table.

However, while playing around your functional requirement with the fresh new Tomahawk library for JSF 2.0 and adding <f:ajax> functionality to be able to disable/enable the necessary components with help of ajaxical powers, I unfortunately encountered a bug in Tomahawk. Inside <t:selectOneRadio>, the <f:ajax> incorrectly renders its client ID instead of the one of <t:radio> as argument for the ajax call which caused the ajax function to broke. I've reported it as Tomahawk issue 1551.

I don't see other clean solutions to achieve this complex (at least, in JSF component terms) requirement. Until the Tomahawk guys get it fixed, your best bet is introducing a temporary JS based workaround to fix the incorrect argument for the ajax call during onload. For your information only, here's how the form would look like:

<style>li { list-style-type: none; }</style>
...
<h:form>
    <t:selectOneRadio id="tasks" value="#{bean.task}" layout="spread">
        <f:selectItems value="#{bean.tasks}" />
        <f:ajax event="click" render="@form" />
    </t:selectOneRadio>
    <ul>
        <li><t:radio for="tasks" index="0" /></li>
        <li><t:radio for="tasks" index="1" />
            <t:selectOneRadio id="processes" value="#{bean.process}" layout="spread" disabled="#{bean.task != 'task2value'}">
                <f:selectItems value="#{bean.processes}" />
                <f:ajax event="click" render="@form" />
            </t:selectOneRadio>
            <ul>
                <li><t:radio for="processes" index="0" /></li>
                <li><t:radio for="processes" index="1" /></li>
                <li><t:radio for="processes" index="2" />
                    <h:inputText value="#{bean.otherProcess}" disabled="#{bean.process != 'process3value'}" />
                </li>
            </ul>
        </li>
        <li><t:radio for="tasks" index="2" />
            <ul>
                <li><h:inputText value="#{bean.brand1}" disabled="#{bean.task != 'task3value'}" /></li>
                <li><h:inputText value="#{bean.brand2}" disabled="#{bean.task != 'task3value'}" /></li>
            </ul>
        </li>
    </ul>
</h:form>

Too bad that the standard JSF implementation doesn't support a flexible radiobutton component like that.

BalusC
Great stuff as usual! Thanks alot. I haven't worked with myFaces, but will give it a whirl. Thanks again!
Zack
Note that "MyFaces" is actually another JSF implementation (competes with Mojarra). You shouldn't have the need to replace Mojarra with MyFaces. Tomahawk is an extended component library developed by the MyFaces guys, but you can use it as good on Mojarra or any other JSF implementation.
BalusC