JavaScript / jQuery OnChange Code Not Working

JavaScript / jQuery OnChange Code Not Working

MagicSquaresMagicSquares Posts: 16Questions: 5Answers: 0

I have a table, built from database content, and on each row, there is an input field at the right of the row.

When a user enters something in that input field and tabs out of it, an Update button appears (which, when clicked, will update the database via an AJAX call).

See the attached screenshot.

This is the HTML code for this input field and the associated Update button:

<td data-order="" valign="top" align="center"><input type="text" id="lt-1729" class="ltinput" name="lead_time_1729" value="" size="4"><br><span id="cl-1729" class="lt_input"><button id="ltb-1729" class="invis ltbutton" style="background-color:#FF9A00;">Update</button></span></td>

This is the JavaScript / jQuery code that shows or hides the Update button based on whether the contents of the input field have changed:

    $('.ltinput').on('change', function() {
        var ltbid = "#".concat(this.id.replace("lt-", "ltb-"));
        if (this.value == "") {
            $(ltbid).css('visibility', 'hidden');
        } else {
            $(ltbid).css('visibility', 'visible');
        }
    });

And this is the DataTables initialization code:

<script type="text/javascript">
    $(document).ready(function(){
$('#event-results').dataTable( {
    "language": [ {
        "decimal": ".",
        "thousands": ","
    } ] ,
    "order": [[ 1, "asc" ]],
    "paging": true,
    "pageLength": 5,
    "pagingType": "full_numbers",
    "searching": true,
    "autoWidth": false,
    "info": true,
    'aoColumnDefs': [ { 'bSearchable': false, 'bVisible': true, 'bSortable': false, 'aTargets': [ 0 ] } ]
} );
    });
</script>

So, the problem is that my code works fine on the first page of the table (i.e. the Update button appears), but if I select a different page, or do a search for a particular entry, the OnChange code show above is not recognizing that anything has changed and does therefore not display the Update button.

Since my HTML / JavaScript / jQuery code is working as expected on the first page of the table, I am assuming that something in the way I have set up my DataTables is causing the problem. Maybe it's to do with the DataTables pagination that results in a new set of data being displayed not being reflected on the page?

Any thoughts on how to fix this?

This question has accepted answers - jump to:

Answers

  • colincolin Posts: 15,146Questions: 1Answers: 2,586
    Answer ✓

    It sounds like you need delegated events, see this section of the FAQ.

    If that doesn't help, we're happy to take a look, but as per the forum rules, please link to a test case - a test case that replicates the issue will ensure you'll get a quick and accurate response. Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.

    Cheers,

    Colin

  • MagicSquaresMagicSquares Posts: 16Questions: 5Answers: 0

    Colin,

    Thank you so much for that!

    I have tried to implement the delegated event code from the example, but I am having trouble working out how to obtain the id of the input field that has been changed.

    Here is my HTML code for the table:

    <table id='event-results' class='cb extratop extrabottom' width='95%' align='center' border='1' cellpadding='10'>
        <thead>
            <tr>
                <td valign='top'><b>Active?</b></td>
                <td valign='top'><b>Event</b>&nbsp;</td>
                <td valign='top'><b>Type</b>&nbsp;</td>
                <td valign='top'><b>Category</b>&nbsp;</td>
                <td valign='top'><b>Starts</b>&nbsp;</td>
                <td valign='top'><b>Ends</b>&nbsp;</td>
                <td valign='top'><b>Lead Time</b>&nbsp;</td>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td valign='top' align='center'><span id='cs-1728' class='sel_button'><img id='e-1728' src='/images/square-check.png' width='16' height='16' border='0' alt='Active through Category settings' title='Active through Category settings'/></span></td>
                <td valign='top'><a id='el-1728' href='https://duckduckgo.com/?q=A%27Phabet+Day+or+No+%27L%27+Day' target='_blank' title='1728'>A'Phabet Day or No 'L' Day</a></td>
                <td valign='top'>Nat'l. Day</td>
                <td valign='top'><span style='background-color:#C0FFC0;'>Fun (60)<span></td>
                <td valign='top'>2022-12-25</td>
                <td valign='top'>2022-12-25</td>
                <td align='center' valign='top' data-order=''><input type='text' id='lt-1728' class='ltinput' name='lead_time_1728' value='' size='4' /><br><span id='cl-1728' class='lt_input'><button id='ltb-1728' class='invis ltbutton' style='background-color:#FF9A00;'>Update</button></span></td>
            </tr>
        </tbody>
    </table>
    

    And here is the new jQuery code I am using, based on the example you pointed me to:

    $(document).ready(function () {
    
        var table = $('#event-results').DataTable();
    
         $('#event-results tbody').on('change', '.ltinput', function () {
            var data = table.row(this).data();
            alert('Hello');
        });
        
    })
    

    This code is now working on all pages - when I change the contents of the input field, whose class is 'ltinput', it detects the change and triggers the 'Hello' alert.

    However, I cannot work out how to reference the id of the particular input field that was changed. That id would be 'lt-' followed by a number, as shown in the HTML code above.

    This is the code I was using, and which only worked on the first page, but I'm struggling to work out how to change this to reference the table variable defined at the start of the jQuery code in the example above.

    $(document).ready(function () {
    
        $('.ltinput').on('change', function() {
            var ltbid = "#".concat(this.id.replace("lt-", "ltb-"));
            if (this.value == "") {
                $(ltbid).css('visibility', 'hidden');
            } else {
                $(ltbid).css('visibility', 'visible');
            }
        });
    
    })
    

    Instead of setting the data variable to 'table.row(this).data()', what do I need to specify to set the data variable to only the id of the input field?

    Thanks for any help you can offer.

  • colincolin Posts: 15,146Questions: 1Answers: 2,586

    It would be worth looking at Editor, as that has API methods to determine what is being edited, such as displayed().

    Otherwise, please can you post a test case so we can see it in action,

    Colin

  • kthorngrenkthorngren Posts: 20,315Questions: 26Answers: 4,771
    <input type='text' id='lt-1728' class='ltinput'....
    

    In your event handler just use jQuery .attr() to get the id. Also you will need to pass in the td or tr to the row() API to get the row. See the row-selector docs for details. I think your event handler should look more like this:

         $('#event-results tbody').on('change', '.ltinput', function () {
            var id = $( this ).attr( 'id' );
            var data = table.row( this.closest( 'td' ) ).data();
            alert('Hello');
        });
    

    Kevin

  • MagicSquaresMagicSquares Posts: 16Questions: 5Answers: 0

    Colin,

    Thanks.

    Here is a link to a test case:

    http://live.datatables.net/yupamita/1/edit?html,js,output

    And here is how to recreate the problem:

    1. On the first page of the table, click in one of the Lead Time boxes at the right, enter a number, and then tab out of the field. An Update button should appear below the input box you changed. You don't need to click the Update button (and it probably wouldn't work anyway.)

    2. Page through to the second page of the table and go through the same process (i.e. enter something in a Lead Time box and tab out of that field). The Update button does not appear.

    On my own site, the "Hello" alert is triggered in both of the above situations (I assume the alert command is disabled on this test environment because the messages are not being displayed), which suggests the delegated event code is working in terms of detecting changes on all pages, not just the first - but I just don't know how to access the id of the input field that was changed, which is what I need (and which works on the first page of the table using my original code, which is still present in the test case.

    Again, it's the HTML input field whose class it 'ltinput' (which is the same value for all rows in the table) that I need to access so I can obtain its unique id for that row and then do something with it.

    I really appreciate all the help you're providing! Thank you!

  • kthorngrenkthorngren Posts: 20,315Questions: 26Answers: 4,771
    edited March 2022

    I commented out your original event handler and now it seems to work:
    http://live.datatables.net/yupamita/2/edit

    Kevin

  • MagicSquaresMagicSquares Posts: 16Questions: 5Answers: 0

    Firstly, thank you so much to both of you for your help so far.

    I have made progress with my original problem, thanks to your advice and suggestions, but now I'm stuck with something else that was working on the first page, but isn't any longer.

    Here is a link to the test case:

    http://live.datatables.net/yupamita/4/edit?js,console,output

    The idea is that you can click on the icon in the first column, and a check mark should turn to a cross, or vice versa, and the database should be updated behind the scenes via the AJAX call.

    The back-end code then recreates the img tag and sends it back via the response, and that img tag should then be updated dynamically on successful completion of the AJAX call.

    The back-end code is working, even on the test case - the database is being updated and the response being sent is correct. In other words, the contents of the img tag you can see in the first column:

    <img id='e-1728' src='/images/square-check.png' width='16' height='16' border='0' alt='Active through Category settings' title='Active through Category settings'/>
    

    ...is correctly being recreated by the back-end AJAX code as:

    <img id='e-1728' src='/images/circle-cross.png' width='16' height='16' border='0' alt='Inactive' title='Inactive'/>
    

    The following code, in the AJAX success section, used to work - it changed the img tag on the page:

    $(containerid).html(response);
    

    The containerid correctly contains the id of the span tag that wraps around the img tag in that first column of the table.

    But it is now not updating the table.

    I have tried so many ways to get it to do this, but nothing has worked.

    I hate to ask for yet more help on this problem, but I have run out of ideas on what to try next.

    Have you any ideas on how I need to change this:

    $(containerid).html(response);
    

    ...so that it updates the img tag in the first column of the table, regardless of which page of the table I'm viewing?

    Again, I really appreciate all the help you're providing! Thank you!

  • kthorngrenkthorngren Posts: 20,315Questions: 26Answers: 4,771
    Answer ✓

    Your ajax request doesn't work. This is in the browser's console:

    Access to XMLHttpRequest at 'https://toolarium.club/tools/HRA-Ajax.php' from origin 'http://live.datatables.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

    However the problem is with your jQuery selector. It needs to be prefixed with # to use containerid as an id selector, like this ($("#" + containerid).html(response);.

    I updated your test case to show this. Click on the checkbox in the first row and the test case simulates the response and updates the checkbox with a circle checkbox.
    http://live.datatables.net/yupamita/8/edit

    Kevin

  • MagicSquaresMagicSquares Posts: 16Questions: 5Answers: 0

    Kevin,

    It's weird that the AJAX code is not working now, because it definitely was when i created that test case. And it is working on my site.

    Anyway, thank you SO much for fixing the selector. I have no idea how I missed that. I think, in my original code, the containerid variable had the # mark on the front, and when I had to restructure it to take account of the delegated event, I obviously forgot to add it back.

    Anyway, it seems as though it's working as it should do.

    Again, i really appreciate your help!

Sign In or Register to comment.