Larry Lustig
Larry Lustig

Reputation: 50970

Success function bound to x-editable not executing with correct parameters

I call the following function several times after my page is loaded. The intent is to incrementally load a lot of similarly-formatted companies from the server. For each company I would like to find all the x-editable elements and bind a success handler function. The success handler in each case should call a refresh function passing in the name and id of this particular company.

This all more or less works -- the companies load incrementally, I'm able to find the matching x-editables and bind my success function to them.

The problem is that when the page is fully loaded and I use an x-editable to edit some data the refreshCompany() function is executed but with the wrong company_name and company_guid. The name and id that appear in the Refresh. . . console message are the same for all companies in a container, and always the last one from company list, not the one that appeared in the Load. . . console message.

I believe one of two things may be happening:

How can I modify the following code such that refreshCompany() will be executed using the name and id values at the time the function is bound?

 function loadCompanies(company_list, container_name, link_container_name) {

    var searchTerm = '#' + container_name;

    for (company of company_list)
    {

        var company_name = company.name;
        var company_guid = company.id;
        console.log('Load ' + company_name + ' ' + company_guid);

        $.ajax(
            {
                url : '${fund.name}/' + encodeURIComponent( company_name ),
                type : 'GET'
            }
        ).done (
            function (company_html) {
                var newElement = $(company_html).appendTo('#' + container_name);
                newElement.find('.editable').editable(
                    {
                        success : function (response, newValue) {
                            console.log('Refresh ' + company_name + ' ' + company_guid)
                            refreshCompany(company_name, company_guid);
                        }
                    }
                );
            }
        );

    }
}

Upvotes: 0

Views: 220

Answers (1)

tdbts
tdbts

Reputation: 525

I hope this helps but it seems the problem is that by the time you get a response from the asynchronous GET request you have already looped through all of the companies in the list, so when the success method runs, company_name and company_guid are bound the last company in the list.

I think you should be able to solve this problem with a closure. Perhaps something like defining a function outside loadCompanies like :

function refreshClosure(companyName, companyGuid) {
	return function () {
		console.log('Refresh ' + companyName + ' ' + companyGuid)
		refreshCompany(companyName, companyGuid);
	}
}

...and using it in your code like this:

function loadCompanies(company_list, container_name, link_container_name) {

    var searchTerm = '#' + container_name;

    for (var company in company_list)
    {

        var company_name = company.name;
        var company_guid = company.id;
      
        // Enclose the current value of company_name and company_guid
        var refreshCurrent = refreshClosure(company_name, company_guid);
        
      console.log('Load ' + company_name + ' ' + company_guid);

        $.ajax(
            {
                url : '${fund.name}/' + encodeURIComponent( company_name ),
                type : 'GET'
            }
        ).done (
            function (company_html) {
                var newElement = $(company_html).appendTo('#' + container_name);
                newElement.find('.editable').editable(
                    {
                        success : function (response, newValue) {
                        // Invoke the function returned from the closure
                            refreshCurrent();
                        }
                    }
                );
            }
        );

    }
}

I also changed the for statement in case that was part of the problem. Let me know if this helps at all.

Upvotes: 1

Related Questions