How to pass data to javascript on a WordPress Admin page?

I am building a WordPress plugin to manipulate a custom table in the WordPress database from an Options Settings page. So far, I’m able to query the database and build an HTML table with the results.

ob_start();
// query the database and get the records
// $games contains the records

$htm .= '<table id="pl_table">';
    // header
    $htm .= '<tr>';
        foreach ( $cols as $col ) {
            $htm .= '<th>'.$col.'</th>';
        }
    $htm .= '</tr>';
    // body
    $htm .= '<tr>';
        foreach ($games as $game){
            foreach ($game as $val) {
                $htm .= '<td>'.$val.'</td>';
            }
            $htm .= '</tr>';
        }
$htm .= '</table>';
echo $htm;
$output = ob_get_contents();
ob_end_clean();
echo $output;

So far so good. Now I want to make the first column in the table a button that fires a javascript function.

Read More
$htm .= '<tr>';
foreach ($games as $game){
    foreach ($game as $val) {
        if ($game->ID == $val){
            $htm .= '<td><button type="button"  id="btn'.$val.'" onclick="myFunction()">'.$val.'</td>';
        }
        else {
            $htm .= '<td>'.$val.'</td>';
        }
    }
    $htm .= '</tr>';
}

Here is the function in my admin.js file:

function myFunction() {
    document.getElementById("tboxOut").value = jsgame.ID;
}

In my main plugins page, I have enqueue’d the script file.

wp_enqueue_script('pl_script',plugins_url( 'js/admin.js', __FILE__ ));

When I open the page in a browser and click a button in column 1, the function fires and I can debug it in the browser.

Now, I need to pass the data in $game to this function and populate a bunch of input boxes, but have had no luck. Here is what I’ve tried:

$aryGame = (array)$game;
$htm .= wp_localize_script( 'pl_script', 'jsgame',$aryGame  );
$htm .= '<td><button type="button"  id="btn'.$val.'"onclick="myFunction()">'.$val.'</td>';

But in the browser debuger, I get an error: Uncaught ReferenceError: jsgame is not defined

Obviously, I’m missing some understanding on how to pass data from PHP to the javascript. Any ideas?

Related posts

Leave a Reply

1 comment

  1. You need to use the correct hook (‘admin_enqueue_scripts’) on the server side, to load the js for the admin page and give it a handle. Then localize the js using the proper logic. And in the script, ensure that jQuery is in no-conflict mode (via jQuery(document).ready).

    In other words, whatever is going on server side stays server side. There is nothing returned by the js function (myFunction), so it doesn’t make sense to say $.htm = wp_localize_script(). The object that is localized for js is either an array or a json encoded(str)/decoded(obj) type. If, after doing something with that data type within the script (client side), you want to post modified data back to the server, you do it by submitting the form to options.php. A submit button/event will trigger a php page refresh, so your server code can use the new data. But you’ll need to click the submit button, i.e., trigger the POST event.

    Here’s how it should look:

    In PHP

    function custom_enqueue_my_script(){
        //Retrieve any options (settings) already in database.
        $options = get_option('my_option_meta_key');
        //If you need to change the data type, e.g., (json_encode/decode), do it here.
        $data_to_pass = json_encode($options);
        //Enqueue the js file
        wp_enqueue_script('script_handle', plugins_url( 'pluginname/js/or/whatever/myadmin.js', dirname(__FILE__) ) );
        //Localize the js, referencing the handle
        wp_localize_script('script_handle', 'my_local_data', $data_to_pass );
    }
    
    add_action( 'admin_enqueue_scripts', 'custom_enqueue_my_script' );
    
    function custom_wp_settings_callback(){ //presumably, some callback in your options.php workflow.
    
        //Render your section, settings and controls here
        //As well as the form.
        $htm .= '<tr>';
        foreach ($games as $game){
            foreach ($game as $val) {
                if ($game->ID == $val){
                    //You don't need onclick if using jquery
                    $htm .= '<td><button type="button"  id="btn'.$val.'">'.$val.'</td>';
                }
                else {
                    $htm .= '<td>'.$val.'</td>';
                }
            }
            $htm .= '</tr>';
        }
    
    }
    

    In JS

    function myFunction(myNewVal){
        //Do something with myNewVal, such as populating an input field within the form, which will eventually send data back to options.php (server side).
    }
    
    jQuery(document).ready(function($){
        var local_data = my_local_data;
        console.log(local_data);    //To see it working
    
        $('#btnMonopoly').click(function(){
            var myNewVal = $('$btnMonopoly').val();
            myFunction(myNewVal);
        });
    });
    

    This solution is substantially based on this blog post by Pippins Plugins.