14

私は単に ajax リクエストからいくつかのデータを取得しようとしています。ajax呼び出しが機能します-データが取得されることはわかっています。しかし、それは ko.computed の値を設定していないだけです...

        function viewModel() {
            this.Id = ko.observable("@Model.Identity()");
            this.Points = ko.computed({ 
                read: function () {
                    $.ajax({
                        url: '/skills/points',
                        data: { id: this.Id },
                        type: 'get',
                        success: function (data) {
                            return data;
                        }
                    });
                },
                owner: this
            });
        }

したがって、次のような呼び出し...

<span data-bind="text: Points"></span>

ただ機能していません。私が間違っていることを理解するのを手伝ってくれる人はいますか?

アップデート

RPNの提案に従って、次のコードを使用していますが、まったく機能しません。コントローラーを見たり、データを返したりしません...何もしません。与えられた 3 つの例をすべて試しましたが、成功しませんでした。

<script type="text/javascript">
    //an observable that retrieves its value when first bound
    ko.onDemandObservable = function (callback, target) {
        var _value = ko.observable();  //private observable

        var result = ko.computed({
            read: function () {
                //if it has not been loaded, execute the supplied function
                if (!result.loaded()) {
                    callback.call(target);
                }
                //always return the current value
                return _value();
            },
            write: function (newValue) {
                //indicate that the value is now loaded and set it
                result.loaded(true);
                _value(newValue);
            },
            deferEvaluation: true  //do not evaluate immediately when created
        });

        //expose the current state, which can be bound against
        result.loaded = ko.observable();
        //load it again
        result.refresh = function () {
            result.loaded(false);
        };

        return result;
    };

    $(document).ready(function () {
        function User(id, name) {
            this.Id = ko.observable(id);
            this.Name = ko.observable(name);
        }
        function viewModel() {
            var self = this;

            this.User = ko.onDemandObservable(this.Update, this);

            this.Update = function () {
                return $.ajax({
                    url: '/home/user/',
                    data: { id: 1 },
                    dataType: 'json'
                }).pipe(function (data) {
                    return new User(data.Id, data.Name);
                });
            };
        };
        var model = new viewModel();
        ko.applyBindings(model);
        model.User();
    });
</script>

<span data-bind="text: User.Name"></span>

更新 (2)

さらに指示に従って、問題の一部を絞り込みました。viewModel の関数として定義することcallbackはうまくいかないようですが (理由はわかりません)、インライン関数を宣言すると ... 何か違う結果が得られます。それでも機能しません。ここにアップデートがあります。

<script type="text/javascript">
    //an observable that retrieves its value when first bound
    ko.onDemandObservable = function (callback, target) {
        var _value = ko.observable();  //private observable

        var result = ko.computed({
            read: function () {
                //if it has not been loaded, execute the supplied function
                if (!result.loaded()) {
                    callback.call(target);
                }
                //always return the current value
                return _value();
            },
            write: function (newValue) {
                //indicate that the value is now loaded and set it
                result.loaded(true);
                _value(newValue);
            },
            deferEvaluation: true  //do not evaluate immediately when created
        });

        //expose the current state, which can be bound against
        result.loaded = ko.observable();
        //load it again
        result.refresh = function () {
            result.loaded(false);
        };

        return result;
    };

    $(document).ready(function () {
        function User(id, name) {
            this.Id = ko.observable(id);
            this.Name = ko.observable(name);
        }
        function viewModel() {
            var self = this;

            this.User = ko.onDemandObservable(function(){
                $.ajax({
                    url: '/home/user/',
                    data: { id: 1 },
                    dataType: 'json',
                    success: function (data) {
                        self.User(new User(data.Id, data.Name));
                    }
                });
            }, this);

            //this.Update = function () {
            //  $.ajax({
            //      url: '/home/user/',
            //      data: { id: 1 },
            //      dataType: 'json',
            //      success: function (data) {
            //          self.User(new User(data.Id, data.Name));
            //      }
            //  });
            //};
        };
        var model = new viewModel();
        ko.applyBindings(model);
        model.User();
    });
</script>

その後、取得したデータを表示しようとしても失敗します。

<span data-bind="text: User.Name"></span>

アップデート (3)

ちょっとした突破!宣言バインディングを次のように変更すると..

<span data-bind="with: User">
    <span data-bind="text: Id"></span>
    <span data-bind="text: Name"></span>
</span>

それから私は結果を見始めています。ほぼ着いてると思いますが…

4

3 に答える 3

15

SLaksが指摘したように、呼び出しが非同期で行われるため、この方法では実行できません。つまり、応答が取得される前に「読み取り」関数が返されます。私はこのようなものをお勧めします:

function viewModel() {
    var self = this;
    this.Id = ko.observable("@Model.Identity()");
    this.Points = ko.observable(0);

    var refreshPoints = function() {
        $.ajax({
            url: '/skills/points',
            data: { id: self.Id() }, // <-- you need () here!
            type: 'get',
            success: function (data) {
                self.Points(data);
            }
        });
    };

    // Now subscribe to the ID observable to update the points whenever the 
    // ID gets changed:
    this.Id.subscribe(refreshPoints);
}
于 2012-12-09T01:26:15.570 に答える
6

監視可能な変数を html 変数にバインドし、ko.computed フィールドのそのフィールドを更新するだけです。ko.computed フィールドを html 変数に直接バインドしないでください。

self.htmlUserName = ko.observable();

self.computedUserName = ko.computed(function () {
    $.ajax(
    ....
    success: function (result) {
    self.htmlUserName(result);
    }
}
于 2013-03-13T16:18:00.530 に答える
2

ノックアウトバインディングは、非同期計算をサポートしていません。

代わりに、通常のプロパティを使用して、AJAXリクエストの結果に設定する必要があります。
依存プロパティの変更ハンドラーでAJAXリクエストを再送信することで、監視可能にすることができます。

別のプレースホルダー値を使用して、バインドされたUIに読み込みインジケーターを追加することもできます。

于 2012-12-09T01:25:25.293 に答える