WordPress AJAX Plugin Not Updating DIV Element Content

I’m building a WordPress plugin that utilizes AJAX to retrieve information and show it in a specific DIV element. Unfortunately, the content isn’t refreshing as intended.

My JavaScript code:

function fetchStudentRecords(user_id) {
  
  // Check if jQuery is loaded
  if (typeof jQuery === 'undefined') {
    console.error('jQuery not available. Make sure jQuery is loaded first.');
    return;
  }

  // Get form values
  var class_name = document.getElementById("class_name").value;
  var $displayArea = $('#studentRecordsDisplay');
  var user_id = user_id || document.getElementById("user_id").value;
  console.log("Class Name: " + class_name);
  console.log("User ID: " + user_id);

  // Check if required fields are filled
  if (!user_id || !class_name) {
    alert("Both User ID and Class Name are required.");
    return;
  }

  alert("Fetching Records for User ID: " + user_id + " in Class: " + class_name);

  $displayArea.html('<p>Loading Records...</p>');

  // AJAX call to get student records
  $.ajax({
    url: ajaxurl,
    type: 'POST',
    data: {
      action: 'get_student_records',
      user_id: user_id,
      class_name: class_name,
      days_range: 30
    },
    success: function(response) {
      $displayArea.html(response);
    },
    error: function(xhr, status, error) {
      $displayArea.html('<p>Failed to load records. Try again later.</p>');
      console.error('AJAX Error:', status, error);
    }
  });
}

My PHP handler function:

// Hook for logged-in users
add_action('wp_ajax_get_student_records', 'get_student_records');

// Hook for non-logged-in users
add_action('wp_ajax_nopriv_get_student_records', 'get_student_records');

function get_student_records($user_id, $class_name, $days_range) {

    global $wpdb;

    $query = "CALL sp_get_student_records('$user_id', '$class_name', $days_range);";
    $wpdb->query($query);
    $student_records = $wpdb->get_results($query, ARRAY_A);

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

    // Build HTML output
    $html = "<table><tr><th>Date</th><th>Score</th></tr>";

    foreach ($student_records as $record) {
        $html .= "<tr>";
        $html .= "<td>{$record['Date']}</td>";
        $html .= "<td>{$record['score']}</td>";
        $html .= "</tr>";
    }
    $html .= "</table>";

    return $html;
}

Console error I’m getting:

error   @   my_custom_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
fetchStudentRecords  @   my_custom_script.js:48
onchange    @   ?page_id=1238&user_id=954894:516
handleMouseUp_  @   unknown

I want the AJAX response to correctly update the displayArea container with the data returned. What might be causing this problem?

Been there, done that. Everyone’s hitting the PHP issues but honestly, this whole setup needs a better approach.

You could fix the WordPress AJAX handler by echoing instead of returning and adding wp_die(). But you’re juggling multiple moving parts that can break - PHP handlers, script localization, database calls, and all that WordPress-specific stuff.

I switched to automation workflows for this type of real-time data update. Way cleaner and more reliable.

Set up a workflow that triggers when your form data changes, fetches student records from your database, and pushes updates directly to your frontend. No more wrestling with WordPress AJAX quirks or debugging mysterious jQuery errors.

The workflow handles database calls, formats your HTML response, and updates your DIV element automatically. Plus you get better error handling and can easily add features like caching or real-time notifications.

I use this pattern for all our internal dashboards now. Much less headache than traditional AJAX implementations.

Check out the automation approach here: https://latenode.com

Yeah, the double execution is definitely a problem, but there’s another issue that might be breaking things. Your PHP function parameters don’t match what WordPress wants - AJAX handlers shouldn’t take parameters. Pull your data from $_POST instead.

You’ve also got a SQL injection vulnerability. You’re throwing variables straight into your query without sanitizing them. Use prepared statements or at least run everything through sanitize_text_field() and intval() first.

I’d add some debugging to your PHP function too. Use error_log() to dump the $_POST data and see if your AJAX call is actually hitting the handler. Sometimes the request never makes it through WordPress’s routing.

Also check that your plugin is enqueueing the script properly. If it’s not loading right, you’ll get random jQuery errors that don’t tell you what’s really wrong.

Yeah, the PHP function structure is your main problem, but there’s another issue that’ll bite you later. Your JavaScript calls ajaxurl, but you need to localize this variable in WordPress first. Without it, ajaxurl stays undefined and your request never reaches the server.

Add this to your plugin when you enqueue the script:

wp_localize_script('your-script-handle', 'ajax_object', array(
    'ajax_url' => admin_url('admin-ajax.php')
));

Then use ajax_object.ajax_url in your JavaScript instead of ajaxurl. I see this mistake all the time - it causes silent failures. Also heads up about that stored procedure - calling it twice can mess things up depending on how you wrote your SP.

quick fix - you’re using ajaxurl but that’s only available on admin pages by default. for frontend pages you need to define it yourself or use wp_localize_script like others mentioned. also check your nonce verification isn’t blocking the request - wordpress can be picky about that.

your php function isn’t echoing anything. wordpress ajax handlers need to echo the response and end with wp_die(). add echo before your return statement, then call wp_die() after. also, grab your function parameters from $_POST instead of function arguments.

Your PHP function signature is wrong, and you’re not handling the data correctly. WordPress AJAX handlers don’t get parameters directly - you have to pull them from $_POST. Fix your function like this:

function get_student_records() {
    $user_id = sanitize_text_field($_POST['user_id']);
    $class_name = sanitize_text_field($_POST['class_name']);
    $days_range = intval($_POST['days_range']);
    
    // your existing code here
    
    echo $html; // echo instead of return
    wp_die(); // required for WordPress AJAX
}

Also, you’re running that stored procedure call twice which will cause problems. Drop the first $wpdb->query($query); line since get_results() already executes it.