Vinyl Warmth Vinyl Warmth - 3 months ago 6
Javascript Question

Why isn't my jQuery function being executed when a value is greater than?

I have a table with a row defined like this:

<tr>
<td id="to-watch">
@Model.Results.Seats
</td>
</tr>


Edit: The table values are being updated by ajax calls to an action which is returning data to the table in a partial

I want to log to the console when the value is greater than 2, here is the jQuery code I have:

$('#to-watch')
.change(function () {
if ($('#to-watch').val() > 2) {
console.log("************ WINNER ***************");
}
});



I have checked in Chrome debugging tools nothing is being logged to the console when the value is greater than 2 - I rarely use jQuery / JavaScript, and after some looking, haven't been able to find the answer..


Edit: I'm making the ajax call like this:

$(document).ready(function () {

(function loop(i) {
setTimeout(function () {
callAjax(i);
//console.log("works " + i);
},
500); // ms
function callAjax(i) {
$.ajax({
url: '/Home/StartElection',
type: 'POST',
data: "test",
async: true
})
.done(function (partialViewResult) {
$("#partialTable").html(partialViewResult);
}).always(function () {
if (--i) loop(i);
});
};
})(650);
});

Answer

There are a couple of problems here.


Firstly, the change event is for input fields. It will execute the callback whenever the value of the input field changes.

There is an equivalent for when any html changes, using Mutation Observers, but it's overly complex for this scenario, as you know when the html changes, and it is done via your code.


Secondly, you are attaching an event listener to #to-watch, which I assume is nested inside #partialTable. Now we already know the change event won't work anyway, but even if this was an input field, we would have the following problem:

  1. Attach listener to DOM element with #to-watch
  2. Make ajax call
  3. On return of ajax call, replace all of #partialTable with a new version of it.
  4. The old #to-watch element is now gone, and so is it's event listener. It can't be triggered anymore.

The solution to this is called event delegation. Meaning you attach the listener to a parent element that doesn't change, and it checks if any child elements matching the selector are changed. This means that id the child elements were changed dynamically, the listener will still work.


Then there are also the aforementioned:

$('...').text() will give you the contents of any DOM element, where as $('...').val() will give the value of an input field

JQUERY .text() docs

JQUERY .val() docs

You want to do a numerical comparison (X > Y), so you should convert the string "2" which is the text of $('#to-watch') into an integer with parseInt(x)


The solution to your problem

When you update the #partialTable, you know that the #to-watch element has received a new value, so now is the time to check it:

      function callAjax(i) {
        $.ajax({
            url: '/Home/StartElection',
            type: 'POST',
            data: "test",
            async: true
        }).done(function (partialViewResult) {
            $("#partialTable").html(partialViewResult);
            if (parseInt($('#to-watch').text()) > 2) {
              console.log("************ WINNER ***************");
            }
        }).always(function () {
            if (--i) loop(i);
        });
    };