0

I have some code with dynamically expanding menus. From my Python Django view, I am passing a JSON array to set the status of checkboxes to checked. There is a hidden div which loads the check boxes, but I can only change the status when there is an alert used.

The code is below and HTML of one of the divs looks as below:

for (var key in interestsselected) {
  genres = interestsselected[key];
  //Tick interest
  $("#id_interest_" + key).prop("checked", true);
  getSubinterests(key); //Gets the sub menu
  $("#interest-" + key).show(); //Hiding or showing makes no difference
  //alert($("#interest-"+key)); //Will work if this line is uncommented
  for (i = 0; i < genres.length; i++) {
    $("#" + key + "-" + genres[i]).prop("checked", true);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="offset-sm-1 subinterests" id="interest-5" style="">
  <label class="interest"><input type="checkbox" class="subinterest 5" id="5-FA" name="genre[]" value="5-FA">Factual</label><br>
  <label class="interest"><input type="checkbox" class="subinterest 5" id="5-SF" name="genre[]" value="5-SF">Science Fiction</label><br>
  <label class="interest"><input type="checkbox" class="subinterest 5" id="5-TH" name="genre[]" value="5-TH">Thriller</label><br>
  <label class="interest"><input type="checkbox" class="subinterest 5" id="5-SU" name="genre[]" value="5-SU">Superhero</label><br>
  <label class="interest"><input type="checkbox" class="subinterest 5" id="5-F" name="genre[]" value="5-F">Fantasy</label><br>
  <label class="interest"><input type="checkbox" class="subinterest 5" id="5-H" name="genre[]" value="5-H">Horror</label><br>
</div>

The code above is already encased within $(document).ready. I have tried encasing the inner for loop with another $(document).ready, but that doesn't work. I have tried adding the inner for loop as part of the function getSubinterests, passing the genres array to it, but that is the same story.

I have tried encasing the for loop in "$("#interest-"+key).ready", but still the same, I have tried "$("#interest-"+key).load", but get an error so tried "$("#interest-"+key).ready("load",function", same problem. I have tried all of these again with "$("#"+key+"-"+genres[i])", but still the same issue.

The code below is the getSubinterests function:

  function getSubinterests(interestid) {
$.ajax({
  type: "POST",
  url: "/user/getsubinterests/",
  data: { csrfmiddlewaretoken:'{{ csrf_token }}',
          interestid: interestid },
  success: function(data) {
    //console.log(data);
    var interesttext = "";

    for (var key in data) {
      //Add returned data under the interest
      interesttext = interesttext + "<label class='interest'><input type='checkbox' class='subinterest "+interestid+"' id='"+interestid+"-"+key+"' name='genre[]' value='"+interestid+"-"+key+"' >"+data[key]+"</label><br>";
      //alert(data[key]);
    }
    $("#interest-"+interestid).html(interesttext);
    //Capture clicks on the checkboxes that have been added
    $(".subinterest").click(function() {
      id = $(this).attr('id').split("-")[0];
      if(!($("#id_interest_"+id).prop("checked"))) {
        $("#id_interest_"+id).prop("checked",true);
      }
    });
  }
});

}

SOLUTION:

  function getSubinterests(interestid) {
    $.ajax({
      type: "POST",
      url: "/user/getsubinterests/",
      data: { csrfmiddlewaretoken:'{{ csrf_token }}',
              interestid: interestid },
      success: function(data) {
        //console.log(data);
        var interesttext = "";
        var genres = [];

        if(interestsselected[interestid]) {
          genres = interestsselected[interestid];
        }

        for (var key in data) {
          //Add returned data under the interest
          if (genres.includes(key)) {
            //Check the box
            interesttext = interesttext + "<label class='interest'><input type='checkbox' class='subinterest "+interestid+"' id='"+interestid+"-"+key+"' name='genre[]' value='"+interestid+"-"+key+"' checked>"+data[key]+"</label><br>";
          } else {
            interesttext = interesttext + "<label class='interest'><input type='checkbox' class='subinterest "+
                          interestid+"' id='"+interestid+"-"+key+"' name='genre[]' value='"+interestid+"-"+key+"' >"+data[key]+"</label><br>";
          }
        }
        $("#interest-"+interestid).html(interesttext);
  }

I understood the async problem and took a different approach where the HTML is rendered from within the success of the AJAX call by reading the global variable which contains the JSON.

OptimusPrime
  • 777
  • 16
  • 25
  • This sounds like an async issue, but we can't tell without *the proper* code. Please read [mcve]. It could also be incorrect selectors. – Rafael Apr 06 '19 at 06:31
  • I made you a snippet. It has errors. Fix them first, then create a [mcve] with examples of JSON and how you render it – mplungjan Apr 06 '19 at 06:36
  • `getSubinterests(key);` looks to be async, move `$("#interest-" + key).show(); for (i = 0; i < genres.length; i++) { $("#" + key + "-" + genres[i]).prop("checked", true); }` into its succes function – mplungjan Apr 06 '19 at 06:39
  • I've added the code for the getSubinterests below my post. Is that what you are asking for? Sorry, I am fairly new to stack overflow so not sure. – OptimusPrime Apr 06 '19 at 07:07
  • I have tried adding the inner for loop to the getSubinterests function within the success area and it is the same issue, is that what you mean? – OptimusPrime Apr 06 '19 at 07:08
  • Here is an example of the JSON "5: Array [ "SF" ]". I believe that the errors in the snippet you refer to are because of the getSubinterests function being missing? – OptimusPrime Apr 06 '19 at 07:26
  • Thanks, I understood the issue which was caused by the Async nature of AJAX and took a different approach. I have posted the solution which worked underneath my text. I am happy to mark the ASYNC explanation as the answer. If you're happy to post that as the answer I will mark it as answered or can mark the duplicate as the answer. Not sure how that works, please advise. Many thanks. – OptimusPrime Apr 06 '19 at 10:43

0 Answers0