Multiple Dynamic DataTables on a Page Via WordPress Plugin

Multiple Dynamic DataTables on a Page Via WordPress Plugin

tlarrtlarr Posts: 4Questions: 1Answers: 0
edited October 2021 in DataTables 1.10

Hi all, I have a weird situation. I am writing a WordPress plugin that relies on DataTables for the creation of some nice looking dynamic tables. My current implementation works great with rendering a single table on a page, but when trying to load multiple, only the last call creates an actual DataTable. The other calls just render the $container.

I cannot provide the full code as it is making a call to a server with our credentials, so I will redact that, but it should be applicable to any output, really. I am suspecting it is because the following is called multiple times when there are multiple shortcodes:

var fieldTable = $('#stField_' + props.tournament).DataTable({
                    "info": false,
                    "paging": false,
                    "processing": true,
                    "responsive": {
                        details: false
                    },
                    "searching": false
                });

However, I am unsure of how to change this because I rely on table.row.add to add data to the table. I've seen examples that use a single selector to select all the tables on the page to convert them to a DataTable, but this wouldn't work in my case because I am creating them dynamically. Any suggestions are appreciated.

leaderboard-plugin:

add_action('wp_enqueue_scripts', 'my_register_scripts');
add_action('init','my_register_shortcodes');

function my_register_scripts() {
    wp_register_style('datatables_css', plugins_url('/css/datatables.min.css', __FILE__));
    wp_register_script('datatables_js', plugins_url('/js/datatables.min.js', __FILE__));
    wp_register_script('xmlToJson', plugins_url('/js/xmlToJson.js', __FILE__));

    wp_enqueue_script('jquery');
    wp_enqueue_style('datatables_css');
    wp_enqueue_script('datatables_js');
    wp_enqueue_script('xmlToJson');

    wp_register_script('my_gen_table', plugins_url('/js/generate.js', __FILE__), array('jquery'));
}

function my_register_shortcodes() {
    add_shortcode('player-fields', 'my_gen_table');
}

function my_gen_table($args, $content) {
    $username = $args['username'];
    $password = $args['password'];
    $tournament = $args['tour_id'];
    $results = "REDACTED";

    $container = "<table id='stField_{$tournament}' class='display responsive nowrap' width='100%'><thead><tr style='background: repeating-linear-gradient(45deg, #77d56a, #117ac9); font-weight: bold; color: white'><td>Player</td><td>City</td><td>State</td><td>Seed</td></tr></thead></table>";
    $props = array('uri' => $results, 'username' => $username, 'password' => $password, 'tournament' => $tournament);

    wp_enqueue_script('my_gen_table');
    wp_localize_script('my_gen_table', 'props', $props);

    return $container;
}

generate.js:

jQuery(document).ready(function($) {
    function generate() {
        $.ajax({
            url: props.uri,
            type: 'GET',
            dataType: 'xml',
            success: function (data) {
                // xmlToJson converts the raw xml data to an easy to use JSON object
                var jsonData = xmlToJson(data);

                // Table ID is set in st_generatePlayerField
                var fieldTable = $('#stField_' + props.tournament).DataTable({
                    "info": false,
                    "paging": false,
                    "processing": true,
                    "responsive": {
                        details: false
                    },
                    "searching": false
                });

                // For-each loop with Player fields
                for (var i = 0; i < jsonData.Field.Player.length; i++) {
                    var currentPlayer = jsonData.Field.Player[i];

                    var _name = currentPlayer['@attributes'].player_name;
                    var _city = currentPlayer['@attributes'].city;
                    var _state = currentPlayer['@attributes'].state_cd;
                    var _seed = currentPlayer['@attributes'].player_seed;

                    fieldTable.row.add([_name, _city, _state, _seed]);
                }

                try {
                    fieldTable.draw();
                } catch (error) {
                    console.log(error);
                }
            },
            error: function (error) {
                console.debug(error);
            }
        });
    }

    generate();
});

Answers

  • tlarrtlarr Posts: 4Questions: 1Answers: 0

    Let me add onto this: When I say things break, I mean that only the table created by the last my_gen_table is a DataTable table with data. None of the other calls have any data added to them, they are just the $container.

  • tlarrtlarr Posts: 4Questions: 1Answers: 0

    And another node, the shortcode calls are remnants of my current codebase, forgot to modify for here:

        add_shortcode('player-fields', 'my_gen_table');
    
  • kthorngrenkthorngren Posts: 21,301Questions: 26Answers: 4,946
    edited October 2021

    Without being able to debug the code it would be difficult to say. Are you calling the generate() generate function multiple times? Since ajax is synchronous you might have multiple outstanding ajax requests and when the are processed the props.tournament variable value is the last one generated. I'm not familiar with your environment but I would look t setting a var local to the function scope to the props.tournament value. Something like this:

        function generate() {
            var t =  props.tournament;
            $.ajax({
    .....
                    var fieldTable = $('#stField_' + t).DataTable({
                        "info": false,
                        "paging": false,
                        "processing": true,
                        "responsive": {
                            details: false
                        },
                        "searching": false
                    });
    .......
            });
        }
    

    Not sure that will work but debug your page to see if the props.tournament value is what you expect it to be in the success function. Maybe pass props in as a parameter to generate().

    Kevin

  • tlarrtlarr Posts: 4Questions: 1Answers: 0

    Yes, I am invoking it multiple times as such:
    [player-fields username="random" password="password" tour_id="1015"]
    [player-fields username="random" password="password" tour_id="1016"]

    I added some prints to the beginning, and it seems it's not even entering jQuery(document).ready(function($) twice, which is weirder.

  • kthorngrenkthorngren Posts: 21,301Questions: 26Answers: 4,946

    jQuery(document).ready(function($) twice, which is weirder.

    That event fires once when the page is loaded and ready.

    Kevin

Sign In or Register to comment.