Search code examples
javascriptjsonknockout.jsknockout-mapping-plugin

How to bind anonymous objects using knockout mapping plugin?


I'm trying to list all usernames from this json data:

[{
        "full_name": "root",
        "group": 0,
        "home": "/root",
        "username": "root",
        "id": 1
    }, {
        "full_name": "Owner of many system processes",
        "group": 1,
        "home": "/root",
        "username": "daemon",
        "id": 2
    }, {
        "full_name": "System",
        "group": 5,
        "home": "/",
        "username": "operator",
        "id": 3
    }]

My HTML looks like this:

 <body>
        <h2>Knockout list</h2>
        <ul data-bind="foreach: users">
            <li data-bind="text: username"></li>
        </ul>

        <script type="text/javascript">
            function getUsers()
            {
                return $.ajax
                        ({
                            type: "GET",
                            url: "http://XXX.XXX/api/userinfo",
                            username: "root",
                            password: "meh",
                            cache: false,
                            dataType: "json"
                        });
            }

            getUsers().done(function(results)
            {
                var users = "{users: " + results + "}";
                var viewModel = ko.mapping.fromJS(users);
                ko.applyBindings(viewModel);
            });

        </script>
 </body>

In Console I get this error:

ReferenceError: users is not defined
with($context){with($data||{}){return{'foreach':function(){return users }}}}

I don't think that adding anything to the json is a good idea. I'm trying to use var users = "{users: " + results + "}";, but it is more a desperate step than anything else, I would like to avoid it if possible.

Do you have any idea how to make this work? Thank you.


Solution

  • Given your HTML, your viewmodel needs to have a property named users, as that's what you're iterating over in the foreach loop. I can't be sure, but the line where you create a new object from the results doesn't look right. You can try creating an explicit users property on your viewmodel and assigning the mapped result to it:

    var viewModel = {};
    viewModel.users = ko.mapping.fromJS(data);
    ko.applyBindings(viewModel);
    

    Created a jsfiddle, and it works there.