使用Knockout显示JSON响应的内容

时间:2015-05-08 12:56:58

标签: knockout.js asp.net-web-api

我对Knockout很新,而且确实是Javascript,所以我毫不怀疑我的问题是愚蠢的。但我发现KnockoutJS的文档假设您已经了解了很多关于Javascript的内容,因此这些示例对我来说还不够完整。

我有一个返回JSON数据的REST API,如下所示:

{"$id":"1","$values":
    [
        {"$id":"2",
            "id":14,
            "name":"Bound to pretend",
            "artist":
                {"$id":"3",
                "id":12,
                "name":"Velvet Veins"
                }},
        {"$id":"4",
        "id":13,
        "name":"This Is It",
        "artist":
            {"$id":"5",
                "id":11,
                "name":"Michael Jackson"
            }}
    ]
}

因此响应是ShortAlbumDto个对象的数组,其中一个属性是Artist类型的另一个对象。

我试图使用KnockoutJS在表格中显示这些数据。这是HTML:

<table class="table table-hover">
    <thead>
        <tr>
            <th>Artist</th>
            <th>Name</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: albums">
        <tr>
            <td data-bind="text: artist.name"></td>
            <td data-bind="text: name"></td>
        </tr>
    </tbody>
</table>

我的KnockoutJS组件(在Home组件中使用)是这样的:

相册-latest.js:

define(['knockout', 'text!./albums-latest.html'], function(ko, templateMarkup) {
    function AlbumsLatest(params) {

        var self = this;
        self.albums = ko.observableArray([]);

        $.getJSON('http://localhost:62755/api/album/latest', self.albums)
  }

  // This runs when the component is torn down. Put here any logic necessary to clean up,
  // for example cancelling setTimeouts or disposing Knockout subscriptions/computeds.
  AlbumsLatest.prototype.dispose = function() { };

  return { viewModel: AlbumsLatest, template: templateMarkup };

});

home.html的:

<h2>Home</h2>

<albums-latest></albums-latest>

albums-latest已在startup.js中正确注册:

define(['jquery', 'knockout', './router', 'bootstrap', 'knockout-projections'], function($, ko, router) {

  // Components can be packaged as AMD modules, such as the following:
  ko.components.register('nav-bar', { require: 'components/nav-bar/nav-bar' });
  ko.components.register('home-page', { require: 'components/home-page/home' });

  // ... or for template-only components, you can just point to a .html file directly:
  ko.components.register('about-page', {
    template: { require: 'text!components/about-page/about.html' }
  });

  ko.components.register('albums-latest', { require: 'components/albums-latest/albums-latest' });

  // [Scaffolded component registrations will be inserted here. To retain this feature, don't remove this comment.]

  // Start the application
  ko.applyBindings({ route: router.currentRoute });
});

(我使用yeoman作为脚手架并添加组件)。

我的问题是,当我执行此操作时,Firebug会告诉我artist is not referenced。 CORS已启用,我可以看到Ajax请求触发,WebApi返回数据只是找到 - 我似乎无法以Knockout理解的方式映射它。

1 个答案:

答案 0 :(得分:1)

试试这个:

$.getJSON('http://localhost:62755/api/album/latest', function(r) {
    self.albums(r.$values);
});

在您的情况下,响应直接映射到albums数组(因为getJSON(url, observable)getJSON(url, function(r) { observable(r); })基本相同),但是ajax请求返回一个对象其中$values属性包含实际的专辑数组。