0

I'm putting together dependent drop-downs (Teacher -> Class -> Student) and am having issues with setting the initial state of the drop-downs. Here's the code:

edit_contract.html

{% load crispy_forms_tags %}    
<div>
    <form method="post" id="contractForm" novalidate 
        data-teachers-url="{% url 'wakemeup:ajax_load_teachers' %}" 
        data-classes-url="{% url 'wakemeup:ajax_load_classes' %}" 
        data-students-url="{% url 'wakemeup:ajax_load_students' %}" 
    >
        {% crispy form %}
    </form>
</div>

<script>
    // Update class drop-down when teacher changes
    $("#id_teacheruserid").change(function () {
        update_classes($(this))
      });

    // Update students drop-down when class changes
    $("#id_classid").change(function () {
        update_students($(this))
      });

    function update_teachers() {
        // Get form values
        var url = $("#contractForm").attr("data-teachers-url");
        var contractId = $(document.getElementById("id_contractid")).val();

        $.ajax({                             // initialize AJAX request
          url: url,                         
          data: {
            'contractid': contractId
          },
          success: function (data) {            
            $("#id_teacheruserid").html(data);  // Update "teacheruserid" field
          }
        })

        update_classes(); // Update classes drop-down
    };

    function update_classes() {
        // Get form values
        var url = $("#contractForm").attr("data-classes-url");
        var teacherUserId = $(document.getElementById("id_teacheruserid")).val();
        var contractId = $(document.getElementById("id_contractid")).val();

        $.ajax({                            // initialize AJAX request
          url: url,                         
          data: {
            'teacheruserid': teacherUserId, 
            'contractid': contractId
          },
          success: function (data) {        
            $("#id_classid").html(data);       // Update "classid" field
          }
        })

        update_students(); // Update students drop-down
    };

    function update_students() {
        // Get form values
        var url = $("#contractForm").attr("data-students-url");
        var classId = $(document.getElementById("id_classid")).val();
        var contractId = $(document.getElementById("id_contractid")).val();

        $.ajax({                                // initialize AJAX request
          url: url,                                 
          data: {
            'classid': classId,                     
            'contractid': contractId
          },
          success: function (data) {                
            $("#id_partyuserinfo").html(data);      // Update "partyuserinfo" field
          }
        })
    };

    window.onload = function() {
        // Initial load of drop-down menus
        update_teachers(); // Cascades to update_classes() and update_students()
    };      
</script>

Flow summary

update_teacher()
- update HTML (drop-down options) for "id_teacheruserid" field

update_classes()
- read value from "id_teacheruserid" field (undefined for initial load)
- update HTML (drop-down options) for "id_classid" field

update_students()
- read value from "id_classid" field (undefined for initial load)
- update HTML (drop-down options) for "id_partyuserinfo" field

The problem

The problem I'm seeing is that the script can't access the values in the form fields in the onload() call. For example, this line in update_classes():

    var teacherUserId = $(document.getElementById("id_teacheruserid")).val();

I added an alert(teacherUserId) directly after this line. On initial page load, it returns undefined. However, when I select a different value from the teacher drop-down, the alert displays the expected value.

My guess is that in the initial onload(), the referenced field values/options (i.e. id_teacheruserid) have not been loaded or made available yet. The fields themselves exist, but return undefined values. Once this function completes, though, it seems they are then accessible and the menus behave as expected.

How can I run update_teachers() to do the initial load and have it access the form field values?

halfer
  • 19,824
  • 17
  • 99
  • 186
ravioli
  • 3,749
  • 3
  • 14
  • 28

1 Answers1

1

First of all you can use

$("#id_teacheruserid").val();

instead of

$(document.getElementById("id_teacheruserid"))

Second

you need to grab the option selected value from the dropdown

$("#id_teacheruserid").find(":selected").val() 

to get the selected ID

Third, you need to call next drop down fill function on success callback

$.ajax({                             // initialize AJAX request
          url: url,                         
          data: {
            'contractid': contractId
          },
          success: function (data) {            
            $("#id_teacheruserid").html(data);  // Update "teacheruserid" field
             update_classes();
          }
        })
Teobis
  • 825
  • 5
  • 12
  • You don't need to select the actual ` – Patrick Evans Jul 04 '18 at 03:25
  • i guess this is and old habit from almost never using a non masked select tag, but you are totally right @PatrickEvans – Teobis Jul 04 '18 at 03:31
  • You guys are right! Thanks so much for your quick help, I appreciate it. – ravioli Jul 04 '18 at 03:49
  • This is my first time delving into AJAX/JQuery. Is the code I've written above compatible across most platforms / devices? Are there any gotchas I need to worry about? – ravioli Jul 04 '18 at 03:50
  • @ravioli you are ok, jQuery has pretty good browser compatibility, please DO NOT leave any console.log on IE :D – Teobis Jul 04 '18 at 03:54