How to get checked state of <p:selectBooleanCheckbox> in jQuery

Juan Camilo Mejia picture Juan Camilo Mejia · Aug 12, 2014 · Viewed 12.6k times · Source

Hi i want a textbox enable or disable dependig of a checkbox status

i have this code but nothing happens i´ve tried using others find methods.

document.getElementById('j_idt6:docName')

and

('j_idt6:docName')

But doesn´t works.

This is my whole code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title></title>

</h:head>
<h:body>
<script type="text/javascript"
    src="http://code.jquery.com/jquery-git.js"></script>


<script type="text/javascript">//<![CDATA[ 
$(window).load(function(){
$('#j_idt6\\:singleDoc').change( function() {
var isChecked = this.checked;

if(isChecked) {
    $(this).parents("tr:eq(0)").find('#j_idt6\\:docName').prop("disabled",true); 
} else {  
    $(this).parents("tr:eq(0)").find('#j_idt6\\:docName').prop("disabled",false);
}

});
});//]]>  

</script>


<h:form>

    <p:panel id="panel" header="Test">

        <h:panelGrid columns="1" cellpadding="5">

            <p:outputLabel for="singleDoc" id="msgSingleDoc"
                value="Is a single document." />
            <p:selectBooleanCheckbox id="singleDoc" />

            <p:outputLabel for="docName" value="Name of the document" />
            <p:inputText id="docName" required="false" />


        </h:panelGrid>
    </p:panel>
</h:form>

</h:body>
</html>

I found a different way to find the elements here http://www.mkyong.com/jsf2/primefaces/how-to-get-jsf-id-via-jquery/

I´m using Primefaces 5

but still nothing happens

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>ORC Sysmar</title>
<script type="text/javascript"
src="http://code.jquery.com/jquery-git.js"></script>
</h:head>
<h:body>

<script type="text/javascript">//<![CDATA[ 
$(window).load(function(){
$(PrimeFaces.escapeClientId('formulario:singleDoc')).change( function() {
var isChecked = this.checked;

if(isChecked) {
            $(this).parents("tr:eq(0)").find(PrimeFaces.escapeClientId('formulario:docName')).prop("disabled",true); 
 } else {  
            $(this).parents("tr:eq(0)").find(PrimeFaces.escapeClientId('formulario:docName')).prop("disabled",false);
 }

 });
});//]]>  

</script>




<h:form id="formulario">

<p:panel id="panel" header="Test">

    <h:panelGrid columns="1" cellpadding="5">
        <p:outputLabel for="singleDoc" id="msgSingleDoc"
            value="Is a single document." />
        <p:selectBooleanCheckbox id="singleDoc" />

        <p:outputLabel for="docName" value="Name of the document" />
        <p:inputText id="docName" required="false" />


    </h:panelGrid>
</p:panel>
</h:form>

</h:body>
</html>

Thanks in advance for your time and answers

Answer

BalusC picture BalusC · Aug 25, 2014

Look closer at the generated HTML output.

This,

<p:selectBooleanCheckbox id="singleDoc" />

generates the following HTML (in order to be able to apply jQuery UI look'n'feel on checkboxes):

<div id="formulario:singleDoc" class="ui-chkbox ui-widget">
    <div class="ui-helper-hidden-accessible">
        <input id="formulario:singleDoc_input" name="formulario:singleDoc_input" type="checkbox" />
    </div>
    <div class="ui-chkbox-box ui-widget ui-corner-all ui-state-default">
        <span class="ui-chkbox-icon ui-c"></span>
    </div>
</div>

You're attempting to hook a change event on <div class="ui-chkbox">. This indeed just won't work. It isn't a <input type="checkbox"> as expected by this kind of script which you apparently randomly found on the Internet in some example targeted specifically on <input type="checkbox"> (and a pretty browser-centric example too; hooking change event on checkboxes is namely not MSIE friendly).

You need to listen on click event of the HTML element having among others ui-state-default class (that's thus the one also having ui-chkbox-box class). Then, you should investigate the checked state of the actual <input type="checkbox"> inside the same ui-chkbox container which is being hidden behind the fancy look'n'feel.

So, all in all, this should do:

<h:outputScript target="body">
    $(document).on("click", "#formulario\\:singleDoc .ui-chkbox-box", function() {
        var isChecked = $(this).closest(".ui-chkbox").find(":checkbox").get(0).checked;
        $("#formulario\\:docName").attr("disabled", isChecked); 
    });
</h:outputScript>

Note that I made 4 improvements as well:

  1. Use <h:outputScript target="body"> instead of a clumsy <script>$(window).load().
  2. Use $(document).on(event, selector, function) instead of $(selector).on(event, function), otherwise this all breaks once you ajax-update the elements behind selector.
  3. Use isChecked directly instead of comparing it in an if-else block which sets exactly the same value as isChecked itself.
  4. No need to grab an element which already has an unique ID by DOM traversing. Just grab it directly. There can be only 1 in entire HTML DOM tree.

To make it all yet better, put the script this in a real .js file which you include via <h:outputScript name>. JS code belongs in .js files, not in .xhtml files. To make it yet better, use smart CSS class names instead of IDs. E.g.

<p:selectBooleanCheckbox ... styleClass="fieldtoggler" />

<p:inputText ... styleClass="togglablefield" />
<p:inputText ... styleClass="togglablefield" />
<p:inputText ... styleClass="togglablefield" />

With

$(document).on("click", "form .fieldtoggler .ui-chkbox-box", function() {
    var checked = $(this).closest(".ui-chkbox").find(":checkbox").get(0).checked;
    $(this).closest("form").find(".togglablefield").attr("disabled", checked);
});

This way it's so much better reusable by just specifying the appropriate CSS classes.