Search code examples
javascriptjqueryjquery-mobilecheckbox

Unable to programatically check a checkbox when using jQuery Mobile


I have been trying to mark a set of checkboxes as checked using jQuery. I cannot seem to work out why.

JavaScript:

function getProjects(course){

console.log("getProjects");
var data = {
  "fn" : "pLoad",
  "course" : course,
  "ajax" : "true"
};
$.ajax({
  type: "GET",
  url: SERVICE_URL, //Relative or absolute path to response.php file
  data: data,
  contentType: "application/json",
  success: function(response) {
    console.log("Recieved Projects!");
    console.log(response);
    var i, list = "";
        for (i = 0; i < response.length; i++) {
            var cid = "#" + response[i].name[0];
            console.log("setting checked: " + cid);
            console.log($(cid).length);
            $(cid).attr("checked");
        }
  }
});

}

HTML:

<td id="blockC" style="width:25%">
                <a href="#" id="expand" data-role="button" data-iconpos="notext" data-icon="arrow-l">Expand</a>
                <hr />
                
                <label for="core">Core</label>
                <input id="core" type="checkbox" value ="Core">
                
                <label for="adultScotland"> Adults(Scotland)</label>
                <input id="adultScotland" type="checkbox" value ="adultScotland">
                
                <label for="adultEngland">Adults(England)</label>
                <input id="adultEngland" type="checkbox" value ="adultsEngland">
                
                <label for="cFScotland"> Children and Families(Scotland)</label>
                <input id="cFScotland" type="checkbox" value ="cFScotland">
                
                <label for="cFEngland">Children and Families(England)</label>
                <input id="cFEngland" type="checkbox" value ="cFEngland">
                
                <label for="epilepsy"> Epilepsy</label>
                <input id="epilepsy" type="checkbox" value ="epilepsy">
                
                <label for="noCare">Non Care</label>
                <input id="noCare" type="checkbox" value ="noCare">
                
                <br />
                <hr />
                <br />
                    <form style="width:100%">
                    <input id="name" type="text" placeholder="Name" style="width:100%"/>
                    <input id="link" type="text" placeholder="Link" style="width:100%"/>
                    <a id="save" href="#" data-role="button">Save</a>
                    <a id="delete" href="#" data-role="button">Delete</a>
                    </form>
                </td>

From the Logs I can confirm that cid is using a valid ID every time the script runs. The goal here is that when I click on a 'course' the script will check each checkbox for the projects that the course belongs to.

The log tells me that the server is returning the correct projects.

Why is this not working?

Edit

This is the log:

the Log

<head>
<title>Q learn App Edit</title>
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
<!--<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.4/jquery.mobile-1.4.4.min.css">-->
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.4/jquery.mobile-1.4.4.min.js"></script>>
<script src="script.js"></script>
<style>
    table, th, td {
        border: 1px solid black;
    }
    td {
        padding: 15px;
    }
</style>
</head>

Solution

  • After the comments above, the conclusion is:

    $(cid).prop("checked", true);
    

    If it doesn't work and you're using below jQuery 1.6, try:

    $(cid).attr("checked","checked");
    

    or

    $(cid).attr("checked", true);
    

    If it doesn't work (it should, though), just move with pure js:

    document.getElementById(response[i].name[0]).checked = true;
    

    EDIT!

    Now, the OP was absolutely RIGHT to open such a question, and here is why:

    Using jQuery Mobile 1.4.4 and jQuery 1.11.0 the jQuery mobile compiler ENTIRELY CHANGES THE HTML STRUCTURE OF YOUR DOCUMENT!

    In a nutshell, here is the problem:

    The block :

    <label for="cFEngland">Children and Families(England)</label>
    <input id="cFEngland" type="checkbox" value="cFEngland">
    

    Gets translated into:

    <div class="ui-checkbox">
       <label for="cFEngland" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-checkbox-off">Children and Families(England)</label>
       <input id="cFEngland" type="checkbox" value="cFEngland" data-cacheval="true">
    </div>
    

    Now, after a few tests, you CAN'T regularly toggle the input value, due to the fact that the STYLE of that checkbox is css related, not html or js related.

    In a nutshell, there are basically TWO states:

    State 1 (checkbox OFF) :

    <div class="ui-checkbox">
       <label for="cFEngland" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-checkbox-off">Children and Families(England)</label>
       <input id="cFEngland" type="checkbox" value="cFEngland">
    </div>
    

    Which is rendered as something like that (in a basic fiddle) :

    State 2 (checkbox ON) :

    <div class="ui-checkbox">
       <label for="cFEngland" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-checkbox-on">Children and Families(England)</label>
       <input id="cFEngland" type="checkbox" value="cFEngland" data-cacheval="false">
    </div>
    

    Which is rendered as something like that (in a basic fiddle) :

    As you can see, the checkbox doesn't have any status and its behaviour is NOT related to its property "checked" any further.

    In order to fix this, you have to a few things.

    The solution

    Now, before moving on, I want to firstly explain here a consideration:

    Because you may want, in the future (or... Well.. perhaps just now!) get the BOOLEAN value of that checkbox, we are going to check it and change its checked property. That is because if you actually just set it checked for the jQuery mobile UI, it will not result checked if you try to get its "checked property".

    Now, moving on, I have implemented the following functions to give you a more comfortable way of doing things with that UI:

    function setCheckboxStatus (id, status) {
        status == false ? $('#'+id).parent().find("label[for="+id+"]").removeClass("ui-checkbox-on").addClass("ui-checkbox-off") : $('#'+id).parent().find("label[for="+id+"]").removeClass("ui-checkbox-off").addClass("ui-checkbox-on");
        document.getElementById(id).checked = status;
    }
    
    function toggleCheckbox (id) {
        $('#'+id).parent().find("label[for="+id+"]").hasClass("ui-checkbox-on") ?$('#'+id).parent().find("label[for="+id+"]").removeClass("ui-checkbox-on").addClass("ui-checkbox-off") : $('#'+id).parent().find("label[for="+id+"]").removeClass("ui-checkbox-off").addClass("ui-checkbox-on");
    
        document.getElementById(id).checked ^= 1;
    }
    
    function getCheckboxStatus (id) {
     return $('#'+id).prop("checked");   
    }
    

    Surprisingly, if you manually click a checkbox, it WILL toggle its status, hence you can get its value by using the getCheckboxStatus function.

    Else, if you want to manually set the checkbox value, use the comfort function setCheckboxStatus, passing the ID ("without #") to the function and the status (either true or false).

    If you want to TOGGLE the status of a checkbox (set it to true if false and to false if true), use the comfort function toggleCheckbox (passing the ID, always without "#").

    In your case, so, you will have to change your code to that (after pasting the functions).

    function getProjects(course){
    
    console.log("getProjects");
    var data = {
      "fn" : "pLoad",
      "course" : course,
      "ajax" : "true"
    };
    $.ajax({
      type: "GET",
      url: SERVICE_URL, //Relative or absolute path to response.php file
      data: data,
      contentType: "application/json",
      success: function(response) {
        console.log("Recieved Projects!");
        console.log(response);
        var i, list = "";
            for (i = 0; i < response.length; i++) {
                setCheckboxStatus(response[i].name[0], true);
            }
      }
    });
    
    }
    

    For testing purposes, I've made this:

    http://jsfiddle.net/2gh1qfoo/5/

    feel free to test what you need to there.

    Another possible solution is just to trigger the "click" event on the checkbox, but it may have some strange results on IE9, so this seems to be the clearest and cross-browser solution.