如何使用Ajax和Mapping插件更新我的模型?

时间:2014-02-04 16:34:18

标签: ajax json knockout.js

使用knockout,我想调用Ajax方法并异步更新我的HTML。

我的方法:“GetPopularChannelResult”

我能够恢复json并将其绑定到模型,但无法更新我的视图。

我必须首先创建一个空模型,“频道”,否则在页面加载时,淘汰会说我没有记录。

修改 我正在使用ko.mapping或ko.mapper(测试目的),我仍然遇到麻烦。

https://github.com/LucasLorentz/knockout.mapper https://github.com/SteveSanderson/knockout.mapping

我想我正在迭代一个对象的属性,但我不确定: How to use knockout to iterate over an object (not array)

我可能没有正确构建我的频道模型,我确实注意到它的一些问题,请进一步了解详细信息。

JSON返回 http://jsonblob.com/52f11ec5e4b00cc4750d0dc2

看看上面的json blob,我注意到我有一个24个属性的对象。这可能是我没有看到任何数据的原因吗?

HTML(查看)

<div class="row">
    <div class="col-md-9">
        <img src="~/Content/Images/ajax-loader.gif" id="spinner" class="ajax-loader" alt="ajax loader" />
        @* TODO: link to a video page *@
        <section id="channelResult" class="hide" data-bind="foreach: channel.data.records">
            <p data-bind="text: username"></p>
            <video width="400" height="400" controls>
                <source data-bind="attr: { src: videoUrl }" type="video/mp4" />
            </video>
            <p data-bind="text: description"></p>
        </section>

    </div>
</div>

JS

$(function() {

var channelIdFromUrl = $.url().param('channelId');
var pageFromUrl = $.url().param('page');

// The ViewModel
my.vm = function () {

    var channel = {
            code: ko.observable('waiting for data'),
            data: [
                {
                    count: ko.observable(0),
                    records: [
                        {
                            liked: ko.observable('0'),
                            foursquareVenueId: ko.observable(null),
                            userId: ko.observable(0),
                            private: ko.observable(0),
                            likes: ko.observableArray([{}]),
                            thumbnailUrl: ko.observable('waiting for data'),
                            explicitContent: ko.observable(0),
                            vanityUrls: ko.observableArray([{}]),
                            verified: ko.observable(1),
                            avatarUrl: ko.observable('waiting for data'),
                            comments: ko.observableArray([{}]),
                            entities: ko.observableArray([{}]),
                            videoLowURL: ko.observable('waiting for data'),
                            permalinkUrl: ko.observable('waiting for data'),
                            username: ko.observable('waiting for data'),
                            description: ko.observable('waiting for data'),
                            tags: ko.observableArray([{}]),
                            postId: ko.observable(0),
                            videoUrl: ko.observable('waiting for data'),
                            created: ko.observable('waiting for data'),
                            shareUrl: ko.observable('waiting for data'),
                            myRepostId: ko.observable(0),
                            promoted: ko.observable(0),
                            reposts: ko.observableArray([{}])
                        }
                    ],
                    nextPage: ko.observable('0'),
                    size: ko.observable('0'),
                    anchorStr: ko.observable('waiting for data'),
                    previousPage: ko.observable(null),
                    anchor: ko.observable('waiting for data')
                }
            ],
            success: ko.observable('waiting for data'),
            error: ko.observable('waiting for data')
        },

        getRecords = function () {
            // It returns undefined first round, until json returns...
            return my.vm.channel.data.records;
        },

        channelData = {
            ChannelId: ko.observable(channelIdFromUrl),
            Page: ko.observable(pageFromUrl)
        },

        // TODO: work on this toggle later
        //isPopular = ko.observable(true),
        //toggleChannelButton = function() {

        //    if (this.IsPopular()) {
        //        this.IsPopular(false);
        //        self.btnText('Get Popular');
        //    } else {
        //        this.IsPopular(true);
        //        self.btnText('Get Recent');
        //    }
        //},
        //btnText = ko.observable('Get Recent'),


        loadChannelPopularCallback = function (json) {
            var parsedJson = $.parseJSON(json);
            ko.mapper.fromJS(parsedJson, {}, my.vm.channel);
        },
        loadPopularChannel = function() {
            my.VineDataService.getVineItems(my.vm.loadChannelPopularCallback, channelData, "GetPopularChannelResult");
        };

    return {
        channel: channel,
        channelData: channelData,
        loadChannelPopularCallback: loadChannelPopularCallback,
        getRecords: getRecords,
        loadPopularChannel: loadPopularChannel
        //IsPopular: isPopular,
        //toggleChannelButton: toggleChannelButton,
        //btnText: btnText
    };
}();

my.vm.loadPopularChannel();
ko.applyBindings(my.vm);

JS dataservice.js

// Depends on scripts:
//                         ajaxservice.js
(function (my) {
    "use strict";
    my.VineDataService = {
        getVineItems : function (callback, channelData, method) {
            my.ajaxService.ajaxGetJson(method, channelData, callback);
        }
    };
}(my));

ajax服务

// ajaxService
// Depends on scripts:
//                         jQuery
(function (my) {
    var serviceBase = '/Home/',
        getSvcUrl = function (method) { return serviceBase + method; };

    my.ajaxService = (function () {
        var ajaxGetJson = function (method, jsonIn, callback) {
            $.ajax({
                url: getSvcUrl(method),
                type: 'GET',
                data: ko.toJS(jsonIn),
                dataType: 'JSON',
                contentType: 'application/json; charset=utf-8',
                success: function (json) {
                    callback(json);
                }
            });
        },
            ajaxPostJson = function (method, jsonIn, callback) {
                $.ajax({
                    url: getSvcUrl(method),
                    type: "POST",
                    data: ko.toJSON(jsonIn),
                    dataType: "json",
                    contentType: "application/json; charset=utf-8",
                    success: function (json) {
                        callback(json);
                    }
                });
            };
        return {
            ajaxGetJson: ajaxGetJson,
            ajaxPostJson: ajaxPostJson
        };
    })();
}(my));

我的命名空间

var my = my || {}; //my namespace

通知 在我更新数据之前,我有0:对象 后记,我仍然在我的模型中有这个,我有一个新的记录:Object [0],这很奇怪,因为我认为它会更新旧数据。

在映射之前从console.log输出

code: function observable() {
data: Array[1]
0: Object
anchor: function observable() {
anchorStr: function observable() {
count: function observable() {
nextPage: function observable() {
previousPage: function observable() {
records: Object[0]
__ko_proto__: function (initialValue) {
_latestValue: Array[1]
0: Object
length: 1
__proto__: Array[0]
_subscriptions: Object
arguments: null
cacheDiffForKnownOperation: function (rawArray, operationName, args) {
caller: null
destroy: function (valueOrPredicate) {
destroyAll: function (arrayOfValues) {
equalityComparer: function valuesArePrimitiveAndEqual(a, b) {
extend: function applyExtenders(requestedExtenders) {
getSubscriptionsCount: function () {
hasSubscriptionsForEvent: function (event) {
indexOf: function (item) {
length: 0
name: "observable"
notifySubscribers: function (valueToNotify, event) {
peek: function () { return _latestValue }
pop: function () {
prototype: observable
push: function () {
remove: function (valueOrPredicate) {
removeAll: function (arrayOfValues) {
replace: function (oldItem, newItem) {
reverse: function () {
shift: function () {
slice: function () {
sort: function () {
splice: function () {
subscribe: function (callback, callbackTarget, event) {
unshift: function () {
valueHasMutated: function () { observable["notifySubscribers"](_latestValue); }
valueWillMutate: function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
__proto__: function Empty() {}
<function scope>
size: function observable() {
__proto__: Object
length: 1
__proto__: Array[0]
error: function observable() {
success: function observable() {
__proto__: Object

映射后从console.log输出

__ko_mapping__: Object
code: function observable() {
data: Array[1]
0: Object
anchor: function observable() {
anchorStr: function observable() {
count: function observable() {
length: 1
nextPage: function observable() {
previousPage: function observable() {
records: Object[0]
__ko_proto__: function (initialValue) {
_latestValue: Array[20]
0: Object
avatarUrl: function observable() {
comments: Object
created: function observable() {
description: function observable() {
entities: Object[0]
explicitContent: function observable() {
foursquareVenueId: function observable() {
liked: function observable() {
likes: Object
myRepostId: function observable() {
permalinkUrl: function observable() {
postId: function observable() {
private: function observable() {
promoted: function observable() {
reposts: Object
shareUrl: function observable() {
tags: Object[0]
thumbnailUrl: function observable() {
userId: function observable() {
username: function observable() {
vanityUrls: Object[0]
verified: function observable() {
videoLowURL: function observable() {
videoUrl: function observable() {
__proto__: Object
1: Object
2: Object
3: Object
4: Object
5: Object
6: Object
7: Object
8: Object
9: Object
10: Object
11: Object
12: Object
13: Object
14: Object
15: Object
16: Object
17: Object
18: Object
19: Object
length: 20
__proto__: Array[0]
_subscriptions: Object
arguments: null
cacheDiffForKnownOperation: function (rawArray, operationName, args) {
caller: null
destroy: function (valueOrPredicate) {
destroyAll: function (arrayOfValues) {
equalityComparer: function valuesArePrimitiveAndEqual(a, b) {
extend: function applyExtenders(requestedExtenders) {
getSubscriptionsCount: function () {
hasSubscriptionsForEvent: function (event) {
indexOf: function (item) {
length: 0
mappedCreate: function (a){if(-1!==b.mappedIndexOf(a))throw Error("There already is an object with the key that you specified.");var c=h()?x(a):a;u()&&(a=v(c,a),e.isWriteableObservable(c)?c(a):c=a);b.push(c);return c}
mappedDestroy: function (a){var c="function"==typeof a?a:function(b){return b===m(a)};return b.destroy(function(a){return c(m(a))})}
mappedDestroyAll: function (a){var c=C(a,m);return b.destroy(function(a){return-1!=
mappedGet: function (a){return b()[b.mappedIndexOf(a)]}
mappedIndexOf: function (a){var c=C(b(),m);a=m(a);return e.utils.arrayIndexOf(c,a)}
mappedRemove: function (a){var c="function"==typeof a?a:function(b){return b===m(a)};return b.remove(function(a){return c(m(a))})}
mappedRemoveAll: function (a){var c=C(a,m);return b.remove(function(a){return-1!=e.utils.arrayIndexOf(c,m(a))})}
name: "observable"
notifySubscribers: function (valueToNotify, event) {
peek: function () { return _latestValue }
pop: function () {
prototype: observable
push: function () {
remove: function (valueOrPredicate) {
removeAll: function (arrayOfValues) {
replace: function (oldItem, newItem) {
reverse: function () {
shift: function () {
slice: function () {
sort: function () {
splice: function () {
subscribe: function (callback, callbackTarget, event) {
unshift: function () {
valueHasMutated: function () { observable["notifySubscribers"](_latestValue); }
valueWillMutate: function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
__proto__: function Empty() {}
<function scope>
size: function observable() {
__proto__: Array[0]
error: function observable() {
success: function observable() {
__proto__: Object

1 个答案:

答案 0 :(得分:0)

我想出了问题,我映射的模型不正确。

我正密切关注json并与映射的json进行比较,我注意到它中有一个额外的对象。这导致我清理了我的频道映射。

内部 my.vm = function(){我注意到数据是一个对象,所以它不需要这些人“[]”。然后我注意到了

var channel = {
            data: {
                records: [
                    {
                        username: ko.observable(),
                        description: ko.observable(),
                        videoUrl: ko.observable()
                    }
                ],
            },
        },

然后我注意到我的数据根本没有刷新,所以我在回调方法中移动了我的绑定。这是一个临时修复,我不明白为什么数据不只是刷新?

如果有人知道为什么会这样,我真的很想知道。

loadChannelPopularCallback = function(json) {
                ko.mapping.fromJSON(json, {}, my.vm.channel);
                ko.applyBindings(my.vm);
            },