gal007 gal007 - 7 days ago 5
Javascript Question

Adding new moodle UI elements according to the onchange event of a select element

I'm new in moodle and I always programmed at client-side. I think maybe I'm missing something because of that reason. I need to provide the user with diverse UI elements, according to what he selects in a combo. So I was thinking in writing the lements according to a strategy (design pattern). From an object in the mod_form.php, I was trying to execute something like this:

$this -> _form -> addElement('select', 'displayStrategy', get_string('displayStrategy', 'xForum'), $displayStrategy, array('onchange' => 'javascript: function loadStrategy(selVal){

$.ajax({
type: "POST",
url: "../mod/xForum/action/displayStrategy.php",
data: { class: selVal }
}).done(function( msg ) {
console.log("Strategy was executed");
});
}; loadStrategy(this.value);') );


That is being executed and the log is printed in the console, but the content in displayStrategy.php is never executed, a "loading" effect is added to the current view and a last problem is I also need to call a function in the same object that is writting the UI ( the one in mod_form.php that executes all the $this -> _form -> addElement(...))

Can you give me a hand? How can I execute those methods according to the strategy?

Thanks a lot!

Answer

I did the following to achieve this:

  1. Put your script on a separate document and call it within your file_form.php:

    // Get data dynamically based on the selection from the dropdown
    $PAGE->requires->js(new moodle_url('/blocks/mymodulename/js/myscript.js'));
    
  2. The file myscript.js has the ".change" functions to identify when the "select" was changed and ".load" to get the data from the file getter.php passing the parameter from the select that changed. Also notice the prefix #id_ before departmentid and studentid, if you inspect the elements, that's how the are actually called.

    window.onload = init;
    
    function init() {
    
        // When a select is changed, look for the students based on the department id
        // and display on the dropdown students select
        $('#id_departmentid').change(function() {
            $('#id_studentid').load('getter.php?departmentid=' + $('#id_departmentid').val());                                
        });
    
    }
    
  3. On the getter.php file, capture the parameter sent through $_GET method, do your query and echo your results. So file getter.php would look like this:

    <?php 
    require_once("../../config.php");
    global $DB;
    
    // Get the parameter
    $departmentid = optional_param('departmentid',  0,  PARAM_INT);
    
    // If departmentid exists
    if($departmentid) {
    
        // Do your query 
        $query = 'SELECT * FROM {table_without_prefix} WHERE departmentid = ' . $departmentid;
        $student_arr = $DB->get_records_sql($query, null,  $limitfrom=0,  $limitnum=0);
    
        // echo your results, loop the array of objects and echo each one
        echo "<option value='0'>All Students</option>";
        foreach ($student_arr as $student) {
            echo "<option value=".$student->id.">" . $student->fullname . "</option>";  
        }
    
    }
    ?>
    
  4. Finally your file_form.php would have the 2 selects, one with the options, and the other with where you need to show the results.

    $mform->addElement('select', 'departmentid', "Select Department", $department_array);
    $student_array = array("All Students");
    $mform->addElement('select', 'studentid', "Select Student", $student_array);
    
  5. Here is a quick video of the results: http://screencast.com/t/KDtiWzDN

I hope it helps!