javascriptphpajaxwordpresswordpress-plugin-creation

Using the AJAX WordPress Plugin to change values on a DIV container


I am working on a simple AJAX WordPress plugin. The plugin needs to make a call and then pass the results using AJAX.

Here is my function in JavaScript:

function courseGradeHistory(student_id) {
  
  // Ensure jQuery is available
  if (typeof jQuery === 'undefined') {
    console.error('jQuery is not defined. Please ensure jQuery is loaded before this script.');
    return;
  }

  // Get course code and student ID from the input fields
  var course_code = document.getElementById("course_code").value;
  var $resultsContainer = $('#studentCourseSchedule');
  var student_id = student_id || document.getElementById("student_id").value;
  console.log("Course Code: " + course_code);
  console.log("Student ID: " + student_id);

  // Validate inputs
  if (!student_id || !course_code) {
    alert("Please provide both Student ID and Course Code.");
    return;
  }

  alert("Loading Course History for Student ID: " + student_id + " and Course Code: " + course_code);

  $resultsContainer.html('<p>Loading Courses...</p>');

  // Make AJAX request to fetch course grade history
  // Ensure that 'ajaxurl' is defined in your WordPress env
  $.ajax({
    url: ajaxurl,
    type: 'POST',
    data: {
      action: 'connect_course_history',
      student_id: student_id,
      course_code: course_code,
      numberofdays: 30
    },
    success: function(data) {
      $resultsContainer.html(data);
    },
    error: function(xhr, status, error) {
      $resultsContainer.html('<p>Error loading courses. Please try again.</p>');
      console.error('AJAX Error:', status, error);
    }
  });
}

And below is my corresponding PHP function:

// Register action for authenticated users
add_action('wp_ajax_connect_course_history', 'connect_course_history');

// register action for unauthenticated users
add_action('wp_ajax_nopriv_connect_course_history', 'connect_course_history');

function connect_course_history($student_id, $course_code, $numberofdays) {

    global $wpdb;

    $sql = "CALL sp_connect_course_history('$student_id', '$course_code', $numberofdays);";
    $wpdb->query($sql);
    $course_history = $wpdb->get_results($sql, ARRAY_A);

    if (empty($course_history)) {
        return "<p>No course history found for this student.</p>";
    }

    // Prepare the output
    $output = "<table><tr><th>DATE</th><th>Grade</th></tr>";

    foreach ($course_history as $course) {
        $output .= "<tr>";
        $output .= "<td>{$course['DATE']}</td>";
        $output .= "<td>{$course['grade']}</td>";
        $output .= "</tr>";
    }
    $output .= "</table>";

return $output;
}

Below is all that I see in the Developer Console:

    error   @   myplugin_script.js:63
c   @   jquery.min.js?ver=3.7.1:2
fireWith    @   jquery.min.js?ver=3.7.1:2
l   @   jquery.min.js?ver=3.7.1:2
(anonymous) @   jquery.min.js?ver=3.7.1:2
XMLHttpRequest.send     
send    @   jquery.min.js?ver=3.7.1:2
ajax    @   jquery.min.js?ver=3.7.1:2
(anonymous) @   jquery-migrate.min.js?ver=3.4.1:2
e.<computed>    @   jquery-migrate.min.js?ver=3.4.1:2
courseGradeHistory  @   myplugin_script.js:48
onchange    @   ?page_id=1238&student_id=954894:516
handleMouseUp_  @   unknown

I expect the results from the call to update resultsContainer.


Solution

  • Your PHP function connect_course_history($student_id, $course_code, $numberofdays) is declared to accept three arguments. However, when WordPress calls an AJAX action, it doesn't automatically pass $_POST or $_GET variables as direct function arguments.

    <?php
    
    add_action('wp_ajax_connect_course_history', 'connect_course_history_callback');
    
    add_action('wp_ajax_nopriv_connect_course_history', 'connect_course_history_callback');
    
    
    function connect_course_history_callback() {
        global $wpdb;
    
        // IMPORTANT: Retrieve data from $_POST
        
        $student_id   = isset($_POST['student_id']) ? sanitize_text_field($_POST['student_id']) : '';
        $course_code  = isset($_POST['course_code']) ? sanitize_text_field($_POST['course_code']) : '';
        $numberofdays = isset($_POST['numberofdays']) ? intval($_POST['numberofdays']) : 30; 
    
        
        if (empty($student_id) || empty($course_code)) {
            echo "<p>Error: Missing Student ID or Course Code.</p>";
            wp_die(); // Always use wp_die() or die() at the end of AJAX callbacks
        }
    
            $sql = $wpdb->prepare("CALL sp_connect_course_history(%s, %s, %d);", $student_id, $course_code, $numberofdays);
    
        $wpdb->query($sql); 
        
        $course_history = $wpdb->get_results($sql);
        
        if ($wpdb->last_error) {
            error_log("Database Error in connect_course_history: " . $wpdb->last_error);
            echo "<p>Database error: Could not retrieve course history.</p>";
            wp_die();
        }
    
        if (empty($course_history)) {
            echo "<p>No course history found for this student or course.</p>";
            wp_die();
        }
    
        
        $output = "<table><thead><tr><th>DATE</th><th>Grade</th></tr></thead><tbody>";
    
        foreach ($course_history as $course) {
            $output .= "<tr>";
            $output .= "<td>" . esc_html($course->DATE) . "</td>"; 
            $output .= "<td>" . esc_html($course->grade) . "</td>";
            $output .= "</tr>";
        }
    
        $output .= "</tbody></table>";
    
        echo $output; 
        wp_die();    
    }
    ?>
    

    Your JavaScript is mostly fine, as it correctly sends the data. The problem was on the PHP side.

    function courseGradeHistory(student_id_param) { 
      
      if (typeof jQuery === 'undefined') {
        console.error('jQuery is not defined. Please ensure jQuery is loaded before this script.');
        return;
      }
    
      var course_code = document.getElementById("course_code").value;
      var $resultsContainer = jQuery('#studentCourseSchedule'); 
      var student_id = student_id_param || document.getElementById("student_id").value; 
    
      console.log("Course Code: " + course_code);
      console.log("Student ID: " + student_id);
    
      if (!student_id || !course_code) {
        alert("Please provide both Student ID and Course Code.");
        return;
      }
    
      alert("Loading Course History for Student ID: " + student_id + " and Course Code: " + course_code);
    
      $resultsContainer.html('<p>Loading Courses...</p>');
    
      
      jQuery.ajax({ 
        url: ajaxurl, 
        type: 'POST',
        data: {
          action: 'connect_course_history', 
          student_id: student_id,
          course_code: course_code,
          numberofdays: 30 
        },
        success: function(data) {
          $resultsContainer.html(data);
          console.log("AJAX Success:", data); 
        },
        error: function(xhr, status, error) {
          $resultsContainer.html('<p>Error loading courses. Please try again.</p>');
          console.error('AJAX Error:', status, error, xhr.responseText); 
        }
      });
    }