Mario Lopez
Mario Lopez

Reputation: 1465

Dropdown is not populated with KnockoutJS and Ajax

I am trying to populate a dropdown list using knockoutjs from an ajax source that returns json. This select has to get updated when changing the value of another dropdown.

This is my model:

var self = this,
    getClientsRoute = "GetContactsFromCompany";

self.selectedCompany = ko.observable();
self.contacts = ko.computed(function getContactsFromCompany() {
    var companyId = self.selectedCompany();
    if (companyId != "" && companyId != undefined) {
        return $.ajax(getClientsRoute, {
            type: 'GET',
            data: 'companyId=' + companyId
        });
    } else {
        return [];
    }             
});

This is my HTML:

<select class="form-control" name="Client.Id" data-bind="options: contacts,optionsText: 'Name',optionsValue: 'Id'">
</select>

And this is my method that return the JSON string (I´m using .NET MVC):

public JsonResult GetContactsFromCompany(int companyId)
    {
        var contacts = _db.Contacts.Where(c => c.CompanyId == companyId).Select(c =>
            new
            {
                Id = c.Id.ToString(),
                Name = c.Name.ToString()
            }).ToList();

        return Json(contacts, JsonRequestBehavior.AllowGet);
    }

I have seen other solutions to this but I think using the 'computed' method is more clean. Everything seems to work ok, I receive my json data but the dropdown is not populated. I have copied the json string returned by the server and created an observableArray with it and works perfectly, so why is it not working when getting the data from the server?

Thanks for your help.

Upvotes: 2

Views: 694

Answers (1)

PatrickSteele
PatrickSteele

Reputation: 14677

The return value of $.ajax is not the result of the ajax call. You need to provide a success handler that will receive the data upon completion of the AJAX call (ajax calls are asynchronous). What you'll want to do is have a separate observable for your contacts and then hook up a subscription to the companyId and do your ajax call whenever companyId changes:

self.companyId = ko.observable();
self.contacts = ko.observableArray([]);
self.companyId.subscribe(function() { self.loadContacts(); });

self.loadContacts = function() {
    $.ajax(getClientsRoute, {
        type: 'GET',
        data: 'companyId=' + self.companyId(),
        success: function(data) { self.contacts(data); }
    });
}

Upvotes: 2

Related Questions