0
votes

I am trying to bind a KnockoutJS view model from a JSON string which represents a 2d array. However I am facing a problem where only the first level of the array is displayed.

My model looks like this:

function CategoriesModel(categories) {
    var self = this;

    self.categories = ko.observableArray(ko.utils.arrayMap(categories, function (category) {
        return {
            description: category.description,
            checks: ko.observableArray(category.checks)
        };
    }));

    self.addCategory = function () {
        self.categories.push({
            description: "",
            checks: ko.observableArray()
        });
    };

    self.removeCategory = function (category) {
        self.categories.remove(category);
    };

    self.addCheck = function (category) {
        category.checks.push({
            description: "",
            keypoint: "",
            penaltypoints: ""
        });
    };

    self.removeCheck = function (check) {
        $.each(self.categories(), function () {
            this.checks.remove(check)
        });
    };

    self.save = function () {
        self.lastSavedJson(JSON.stringify(ko.toJS(self.categories), null, 2));
    };

    self.lastSavedJson = ko.observable("");
};

The method where I am trying to bind the JSON data is:

function loadData() {
    var rawJSON = '[
        {
            "description":"01", 
            "checks":{"
                    description":"01", 
                    "keypoint":"01", 
                    "penaltypoints":"01"
            }
        },{
            "description":"02", 
            "checks":{
                    "description":"02", 
                    "keypoint":"02", 
                    "penaltypoints":"02"
            }
        }
    ]';

    var parsedJSON = JSON.parse(rawJSON);

    viewModel.categories = ko.mapping.fromJSON(rawJSON);

    ko.applyBindings(viewModel);
}

Can anyone please tell me what my mistake is? Any help will be greatly appreciated.

Edit: I tried to create a jsfiddle (http://jsfiddle.net/EAu2E/4/) but it seems knockout.js and knockout-mapping.js resources aren't loading properly.

1
I have updated your fiddle please look at the updated one jsfiddle.net/EAu2E/7Gabe
Why map from JSON when you can map directly from JS objects?haim770
@haim770 Because the server will be giving back a JSON string, eventually...636f6465

1 Answers

0
votes

The problem was in the JSON string. Although http://jsonlint.com was showing the string below as valid:

var rawJSON = '[
    {
        "description":"01", 
        "checks":{"
                description":"01", 
                "keypoint":"01", 
                "penaltypoints":"01"
        }
    },{
        "description":"02", 
        "checks":{
                "description":"02", 
                "keypoint":"02", 
                "penaltypoints":"02"
        }
    }
]';

Knockout JS was expecting square brackets around the nested list (which also valid JSON), like so:

var rawJSON = '[
    {
        "description":"01", 
        "checks":[{"  //<----- Square bracket required here.
                description":"01", 
                "keypoint":"01", 
                "penaltypoints":"01"
        }]  //<----- Square bracket required here.
    },{
        "description":"02", 
        "checks":[{  //<----- Square bracket required here.
                "description":"02", 
                "keypoint":"02", 
                "penaltypoints":"02"
        }]  //<------ Square bracket required here.
    }
]';