zeristor
zeristor

Reputation: 429

Mapping JSON from an AJAX call in Knockout

I'm starting to use Knockout Mapping, I'm missing something obvious?

When the AJAX call is made the binding fails as the data hasn't yet been returned. One way around that is to set up an empty JSON response to prepolulate the viewmodel, but to me that doesn't seem right. It would be good if the requirement for an initial empty JSON object could be dropped.

Is there way around this? writing this I'm beginning to think delaying the binding until after the first JSON query has returned.

thanks

Upvotes: 1

Views: 688

Answers (3)

zeristor
zeristor

Reputation: 429

The problem came up again, and searched anew.

I found this rather good knockout tips page if you scroll down to "Undefined Properties" it suggests prefixing the parameter with "$data."

To quote "In JavaScript it is an error to attempt to retrieve the value of a variable that is not defined, but it is fine to access an undefined property off of another object"

Thanks for the help, but this is an almost invisible light weight fix.

Upvotes: 0

Christian Phillips
Christian Phillips

Reputation: 18749

Here is a cut down example...

$(function () {
    $(function () {
        function userposition(position, sduid, userName) {

            this.position = ko.observable(position);
            this.userId = ko.observable(sduid);
            this.userName = ko.observable(userName);
        }

        function overallTablesViewModel() {

            this.userpositions = ko.observableArray([]);
            var userpositions = this.userpositions;
            var options = {};

            this.FilterClick = function () {

               options =
                {
                    Prop1: value,
                    Prop2: value
                };

               if (sportId < 1) {
                   toastr.error('You need to select a sport.');
                   return;
               }

                $.getJSON('url', options, function (json) {
                    var mappedData = ko.utils.arrayMap(json, function (up) {
                        return new userposition(up.Position, up.SDUID, up.UserName);
                    });
                    userpositions(mappedData);
                });
            };
        }

        //set up the viewmodel
        var viewModel = new overallTablesViewModel();
        ko.applyBindings(viewModel, $("#overallTablevm")[0]);
    });
});

My example is using a click event, but you can take that out. You can see that the ViewModel calls a url, and the json returned builds an observableArray of userposition.

The view will then have a property userpositions that holds the data.

Upvotes: 1

ColinE
ColinE

Reputation: 70122

I would use a Knockout template, as detailed in the template binding documentation. The basic approach is that you take your current HTML that binds to the results of the AJAX call, and move this into a template.

You then have a property on your top-level view model which is the JSON results that you obtain via the AJAX call:

<div data-bind="template: { name: 'my-template', data: myAjaxResponse}"></div>

Upvotes: 0

Related Questions