Search code examples
javascriptscript-tag

Calling an external JavaScript after a table is loaded


Firstly, please accept my apology if the question has already been asked ... and answered. I personally went through multiple google results, but it seams like the answers are either not relevant or impossible to implement with my level of understanding.

In my ignorance I have taken over a MVC WebApp project in .Net, that I need to redesign the UI for. It is a standard app where users query SQL database using HTML inputs and get some results on the screen for later manipulation.

The problem is that my knowledge of C# equals 0 and my JavaScript knowledge equals 1 on a 0-10 scale, so please treat me like a child when explaining.

To make things easier for myself I have bought a theme based on Bootstrap Paper Design. Now, the sortable table that comes with this has some formatting JavaScript, that was originally on the page, but I moved it out, so now it is loaded from external source with HTML <script> tag. The code is below:

$(document).ready(function () {
    $('#tbl_Customers').DataTable({
        "pagingType": "full_numbers",
        "lengthMenu": [
            [6, 12, 24, -1],
            [6, 12, 24, "All"]
        ],
        responsive: true,
        language: {
            search: "_INPUT_",
            searchPlaceholder: "Search records",
        }
    });
});

When the table is hardcoded the formatting JavaScript does the trick. I guess it is because the JavaScript is loaded after the table. I can be wrong, though. The problem is that the table is being build dynamically, basing on user's input. As far as I understand, JavaScript function gathers user's input, sends it to C# Controller. Then it receives (from C# Model) an HTML string formatted into a table and injects it into an existing <div>. At least this is what I think happens. JavaScript code below:

   // Search function
    function Search_Customer() {
        // Take values from form fields
        p_ref_number = $('#txt_RefNumber').val();
        p_email = $('#txt_Email').val();
        p_fname = $('#txt_FirstName').val();
        p_lname = $('#txt_LastName').val();
        p_add1 = $('#txt_Address').val();
        p_pcode = $('#txt_Postcode').val();
        p_sch = $('#txt_SchoolCode').val();

        // Display alert if all form fields are empty
        if (isEmpty(p_fname) && isEmpty(p_lname) && isEmpty(p_email) && isEmpty(p_sch) && isEmpty(p_pcode) && isEmpty(p_add1) && isEmpty(p_dat) && isEmpty(p_ref_number)) {
            showAlert('Please add search criteria first');
        }
        else {
            p_Data = passSearchValuesToController();

            // Run search function in Controller
            p_URL = '@Url.Action("Get_Contact_Search_Result")';

            // Display the card with search results
            $.post(p_URL, p_Data, function (data_con) {
                $('#displayCustomerResults').html('');
                $('#displayCustomerResults').append(data_con.display);
            });
        };
    };

The <div> the data is injected into is here:

<div id="displayCustomerResults" class="col-md-12"></div>

When this is done, the table is displayed but without the formatting that should be applied by the code from the first function.

I might be wrong, but I assume this happens because the table was added into the page after the formatting JavaScript was loaded. So, on this premise, I further assume I need a way of loading the script after the table is added. I tried a few things, but they all failed. One of the methods I used was adding these three lines of code into the else part of the if statement of the Search_Customer() function.

var tableScript = document.createElement("script");
tableScript.setAttribute("src", "../../Assets/js/custom/search-customer-table.js");
document.body.appendChild(tableScript); 

So, the question is how I can load an external script from within the else part of the Search_Customer() function.

Any suggestions are much appreciated. And if I am being wrong by assuming that the problem is caused by the order of loading then please point me into a right direction.

Thanks a lot in advance.


Solution

  • First, congratulations to your very well presented and phrased question!

    Instead of dynamically adding the script that actually, through $(document).ready(), does its stuff only once when the page has been loaded (which has already happened long before the call to $.post()), you can basically take the contents of the script and execute it right after the append() as I have done in the code below (I haven't been able to test it):

    
       // Search function
        function Search_Customer() {
            // Take values from form fields
            p_ref_number = $('#txt_RefNumber').val();
            p_email = $('#txt_Email').val();
            p_fname = $('#txt_FirstName').val();
            p_lname = $('#txt_LastName').val();
            p_add1 = $('#txt_Address').val();
            p_pcode = $('#txt_Postcode').val();
            p_sch = $('#txt_SchoolCode').val();
    
            // Display alert if all form fields are empty
            if (isEmpty(p_fname) && isEmpty(p_lname) && isEmpty(p_email) && isEmpty(p_sch) && isEmpty(p_pcode) && isEmpty(p_add1) && isEmpty(p_dat) && isEmpty(p_ref_number)) {
                showAlert('Please add search criteria first');
            }
            else {
                p_Data = passSearchValuesToController();
    
                // Run search function in Controller
                p_URL = '@Url.Action("Get_Contact_Search_Result")';
    
                // Display the card with search results
                $.post(p_URL, p_Data, function (data_con) {
                    $('#displayCustomerResults').html('');
                    $('#displayCustomerResults').append(data_con.display);
    
                    // Added this 
                    $('#displayCustomerResults')
                      .find('#tbl_Customers')
                      .DataTable(
                         {
                            "pagingType": "full_numbers",
                            "lengthMenu": [
                               [6, 12, 24, -1],
                               [6, 12, 24, "All"]
                            ],
                            responsive: true,
                            language: {
                                search: "_INPUT_",
                                searchPlaceholder: "Search records",
                            }
                       });
                });
            };
        };
    
    

    What my addition does:

    1. Assumes that the HTML that's been appended to the element with id displayCustomerResults contains an element with id tbl_Customers.
    2. Tries to find() an element with id tbl_Customers in the appended HTML and applies whatever .DataTable() does to this element.