1

Just starting with KnockOut Mapping to read some JSON (using Google Books API) , but can't seem to get it to work. No errors report, but nothing is displayed. Probably a simple issue I overlooked, but thanks for the review.

Markup....

<body>
<h2>Find Cat in the Hat</h2>
   <div>
        <input id="booksearch" />
    </div>
    <div>
        <table>
            <thead>
                <tr>
                    <th>Volumes</th>
                </tr>
            </thead>
            <tbody data-bind="foreach: model.items">
                <tr>
                    <td data-bind="text: model.id"></td>
                </tr>
            </tbody>
        </table>
    </div>
    <input id="btnTest" type="button" value="button" />
</body>
<script src="/Scripts/jquery-1.8.2.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="/Scripts/knockout-2.2.0.js"></script>
<script src="/Scripts/knockout.mapping-latest.js"></script>

Jquery....

$(document).ready(function () {
    //Knockout Test

    $('#btnTest').click(function () {
        var url = "https://www.googleapis.com/books/v1/volumes?q=the+Cat+In+The+Hat";

        var viewModel = {};
        $.getJSON(url, function (data) {
            viewModel.model = ko.mapping.fromJSON(data);
            ko.applyBindings(viewModel);

        });
    });
});
Shoebob
  • 45
  • 1
  • 6

1 Answers1

2

In the $.getJSON success callback you will get back a JavaScript object not a JSON string:

The success callback is passed the returned data, which is typically a JavaScript object or array as defined by the JSON structure and parsed using the $.parseJSON() method. It is also passed the text status of the response

So you need to use ko.mapping.fromJS(data); method instead of ko.mapping.fromJSON(data);

Your fixed code should look like:

$.getJSON(url, function (data) {
    viewModel.model = ko.mapping.fromJS(data);
    ko.applyBindings(viewModel);
});

You also have an another issue in your view: data-bind="text: model.id" should be data-bind="text: id" you don't need the model there because inside the foreach you are in the context of model.items:

<tbody data-bind="foreach: model.items">
    <tr>
        <td data-bind="text: id"></td>
    </tr>
</tbody>

Demo JSFiddle.

nemesv
  • 138,284
  • 16
  • 416
  • 359
  • @nemesv have you considered querying mutliple searches ? NO , error : Uncaught Error: You cannot apply bindings multiple times to the same element. – ProllyGeek Aug 08 '15 at 17:47
  • @ProllyGeek I've never considered multiple searches, the original question was about how to properly parse the response with the mapping plugin and it was never occurred to me that you cannot execute the search twice (anyway the search in the demo only returns a fix list and not actually working). Of course the `ko.applyBindings` has to be called once and with some restructuring of the code (moving the `ko.applyBindings` to the DOM ready and using the mapping plugin a little bit differently) it could work: http://jsfiddle.net/mqna9nxg/ – nemesv Aug 08 '15 at 17:57
  • @nemesv have you tried multiple search on your example ? – ProllyGeek Aug 08 '15 at 18:00