Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery .change() event is only fired once

I have an application that retrieves Project names from a database when the DOM is ready. Each Project is added to a <select><option> in an html <form>. Once the list is populated the user can select a project title, which will request the remaining information from the database specific to that project.

To achieve this I'm using the $.change() jQuery method. Unfortunately, the event is only fired once when the <select> element is created and added to the DOM. Selecting another project from the list does not fire the event, and therefore does not trigger a $.post() call.

$(function(){
    getProjects();
    var firstLoad = true;

    $("select").change(retrieveProject); // Removed parenthesis based on answers

    // On page load, get project names from the database and add them to a Select form element
    function getProjects() {
        var selectionList;
        $.getJSON("php/getProjects.php", function (data) {
            selectionList = "<form><select>";
            for (var i = 0; i < data.length; i++) {
                selectionList += "<option name='prjTitle'>" + data[i].ProjectTitle + "</option>";
            }
            selectionList += "</select></form>";
        }).complete(function() {
           $('#project-selection-menu').append(selectionList).removeClass('hidden');
           firstLoad = false;
        });
    }

    function retrieveProject() {
        if ( firstLoad == true ){
            alert(firstLoad); // This alert fires
            return false;
        } else {
            alert(firstLoad); // This alert doesn't fire
            $.post("php/getProjects.php", function (data) { // This should have been "php/retrieveProject.php"!
                // Do stuff with the returned data
            }).complete(function() {
               console.log("Success.");
            });
        }
    }
)};
like image 533
Roy Avatar asked Jan 15 '14 17:01

Roy


4 Answers

You need to handle event delegation

$(document).on('change', 'select', retrieveProject);

Also remove () next to the method retrieveProject

like image 107
Venkata Krishna Avatar answered Oct 24 '22 11:10

Venkata Krishna


You're not setting up the event handler properly:

$("select").change(retrieveProject);

In your code, you were calling the "retrieveProject" function, and the return value from that function call was being passed as the "change" handler (and of course having no effect). That's why it appeared that the event was being generated upon page load.

When you're working with a function as a value, you don't use () after the function reference — it's the reference itself (the function name, in this case) that you want. That's what needs to be passed to jQuery.

Also — and this is important — make sure that your code is run either in a "ready" or "load" handler, or else that your <script> comes after the <select> element on the page. If the script is in the document head, then it'll run before the DOM is parsed, and it'll have no effect. (Another way to deal with that would be to use an .on() delegated form as suggested in another answer.)


More: it looks like you're overwriting your <select> element when you fetch the content in "getProjects". Thus, you should definitely use the delegated form:

$(document).on("change", "select", retrieveProject);

Also, you should be using local variables in "getProjects":

function getProjects() {
    var selectionList; // keep this local to the function - implicit globals are risky

    $.getJSON("php/getProjects.php", function (data) {
        selectionList = "<form><select>";
        for (var i = 0; i < data.length; i++) {
            selectionList += "<option name='prjTitle'>" + data[i].ProjectTitle + "</option>";
        }
        selectionList += "</select></form>";
    }).complete(function() {
       $('#project-selection-menu').append(selectionList).removeClass('hidden');
       firstLoad = false;
    });
}
like image 33
Pointy Avatar answered Oct 24 '22 09:10

Pointy


you can also do this by using following which will work fine.

$("select").change(function(){retrieveProject()});

or

$("select").on('change',function(){retrieveProject()});
like image 33
Adesh Pandey Avatar answered Oct 24 '22 11:10

Adesh Pandey


Is this what your looking for? To run getProjects once the page loads just call it in your $(document).ready() function. Also you need to properly setup your change handler. See the fiddle for reference.

var firstLoad = true;
getProjects();
$("#selectTest").change(function(){
    retrieveProject();
});

// On page load, get project names from the database and add them to a Select form element
function getProjects() {
    $.getJSON("php/getProjects.php", function (data) {
        selectionList = "<form><select>";
        for (var i = 0; i < data.length; i++) {
            selectionList += "<option name='prjTitle'>" + data[i].ProjectTitle + "</option>";
        }
        selectionList += "</select></form>";
    }).complete(function() {
       $('#project-selection-menu').append(selectionList).removeClass('hidden');
       firstLoad = false;
    });
}

function retrieveProject() {
    if ( firstLoad == true ){
        alert(firstLoad); // This alert fires
        return false;
    } else {
        alert(firstLoad); // This alert doesn't fire
        $.post("php/getProjects.php", function (data) {
            // Do stuff with the returned data
        }).complete(function() {
           console.log("Success.");
        });
    }
}

http://jsfiddle.net/trevordowdle/Mf38E/

like image 45
Trevor Avatar answered Oct 24 '22 10:10

Trevor