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

12,603

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.

Share:
12,603
Juan Camilo Mejia
Author by

Juan Camilo Mejia

Updated on August 16, 2022

Comments

  • Juan Camilo Mejia
    Juan Camilo Mejia over 1 year

    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

  • Juan Camilo Mejia
    Juan Camilo Mejia over 9 years
    BaluscC thanks for your answer, In your javascript i´ve changed "#form\\:singleDoc this for "#formulario\\:singleDoc, because this is the id what I have for the form, but does´t works. It how looks now pastie.org/9501886
  • BalusC
    BalusC over 9 years
    Why did you change click event as shown in my answer by non-existent hover event?
  • Juan Camilo Mejia
    Juan Camilo Mejia over 9 years
    Im sorry because with click doesn´t runs I tried with other events but with the click events looks like this pastie.org/9501915
  • BalusC
    BalusC over 9 years
    Works for me. I'm using PrimeFaces 5.0. I don't have loaded another jQuery file via a manually fiddled <script> tag. PrimeFaces as being a jQuery based JSF component library already auto-includes jQuery all by itself. Try removing that <script> tag on jquery-git.js. Don't forget to check JS console for errors as well.
  • Juan Camilo Mejia
    Juan Camilo Mejia over 9 years
    Man yes its works I just restarted tomcat and works, thaks to teach me so much