0
votes

I have a p:selectOneRadio setup as follows :

<p:selectOneRadio id="positionRadio" value="#{employeeBean.empPosition}" converter="#{empPositionConverter}" layout="custom"
                    required="true" requiredMessage="Please select a position">
    <f:selectItems value="#{employeeBean.positionList}" var="pos"
                                itemLabel="#{pos.name}" itemValue="#{pos}" />
    <p:ajax process="@this" update="@this"/>
</p:selectOneRadio>

<ui:repeat id="iterator" value="#{employeeBean.positionList}" var="template" varStatus="iterStat">
    <div class="form-group" onclick="document.getElementById('employeeForm:positionRadio:#{iterStat.index}').click();">
        <h:outputText styleClass="form-control" value="#{pos.name}"/>
        <p:radioButton for=":employeeForm:positionRadio" itemIndex="#{iterStat.index}" />
        <div style="display: inline">
            <p style="display: inline">
                <h:outputText value="#{pos.description}"/>
            </p>
        </div>
    </div>
</ui:repeat>

I need to check the corresponding radio button if anything in the div containing it is clicked. I am attempting to do this using

onclick="document.getElementById('employeeForm:positionRadio:#{iterStat.index}').click();"

This is only half working. When I click on the div I do see the POST request fire, however the styles aren't updated so none of my radio buttons are checked client side.

This is of course because p:radioButton is rendered as a div with a hidden input radio element and a visible span that is styled accordingly. Why is the span style not updated when clicked via javascript and is there a way to fix it?

Using JSF 2.1.7, PrimeFaces 5.0 and Java 1.7

2

2 Answers

0
votes

I have been working on this problem further and have a solution. I would still prefer a different one, but my current solution is to update the styles manually via javascript.

First off I added a hidden input field outside the ui:repeat to track the previously clicked radio button index

<input type="hidden" name="prevClicked" id="prevClicked" value="-1"/>

I also gave the p:radioButton inside the ui:repeat an id of raBtn and moved the onclick javascript to a function as follows

function radioBtnDivClicked(event, radioIndex){
    // check prevClicked field to revert styles if necessary
    if(document.getElementById('prevClicked').value != -1){
        var prevIndex = document.getElementById('prevClicked').value;
        document.getElementById('employeeForm:iterator:' + prevIndex + ':raBtn').children[1].className = 'ui-radiobutton-box ui-widget ui-corner-all ui-state-default';
        document.getElementById('employeeForm:iterator:' + prevIndex + ':raBtn').children[1].children[0].className = 'ui-radiobutton-icon ui-icon ui-icon-blank';
    }

    // set styles for clicked div
    document.getElementById('employeeForm:positionRadio:' + radioIndex).click();
    document.getElementById('employeeForm:iterator:' + radioIndex + ':raBtn').children[1].className = 'ui-radiobutton-box ui-widget ui-corner-all ui-state-default ui-state-active';
    document.getElementById('employeeForm:iterator:' + radioIndex + ':raBtn').children[1].children[0].className = 'ui-radiobutton-icon ui-icon ui-icon-bullet';
    document.getElementById('prevClicked').value = radioIndex;

    // stop bubbling
    event.stopPropagation();
}

This should be fairly simple to convert to jQuery.

Furthermore I only changed to onclick to

onclick="radioBtnDivClicked(event,#{iterStat.index});"

This works, but I prefer a solution in which the radio button behaves as it does when it is clicked directly(ie Primefaces handles the style changes).

0
votes

You seem to be clicking on the 'wrong' html element. If you look at that id of the generated <p:radioButton... e.g. the first button in the custom layout example in the PrimeFaces showcase:

<div id="j_idt88:opt1" class="ui-radiobutton ui-widget">
    <div class="ui-helper-hidden-accessible">
        <input value="Red" id="j_idt88:customRadio:0_clone" name="j_idt88:customRadio" class="ui-radio-clone" data-itemindex="0" type="radio">
    </div>
    <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default">
        <span class="ui-radiobutton-icon ui-icon ui-icon-blank ui-c"></span>
    </div>
</div>

And create a click on the div with the 'ui-widget' class beneath it

So

$('#j_idt88\\:opt1 .ui-widget').click();  # The \\ is for escaping the colon in the jQuery selector)

Then it works. I tried this and tested in the PrimeFaces 6.0 showcase

You might need to use your own id's or see if there is some logic in the generated ones if you don't explicitly assign id's.