12

私はknockout.jsを初めて使用し、ユーザーを表す次のオブジェクトにバインドしようとしています。

{
    "$id": "1",
    "$values": [
        {
            "$id": "2",
            "Locations": {
                "$id": "3",
                "$values": []
            },
            "Photos": {
                "$id": "4",
                "$values": []
            },
            "UserId": 1,
            "Name": "Test User"
        }
    ]
}

ユーザーは、0個以上の場所、および0個以上の写真を表示できます。

ビューモデル:

function UsersViewModel() {
    var self = this;
    self.users = ko.observableArray();

    var baseUri = 'http://localhost:46241/api/users';

    $.getJSON(baseUri, function (data) {
        self.users = data;
    });
}

$(document).ready(function () {
    ko.applyBindings(new UsersViewModel());
})

HTMLには、次のバインディングが含まれています。

<ul id="update-users" data-bind="foreach: users"> 
     <li> 
            <div><div class="item">User ID</div>
                <input type="text" data-bind="value: $data.UserId" />
            </div>                 
            <div><div class="item">Name</div>
                <input type="text" data-bind="value: $data.Name" />
            </div>                  
     </li> 
</ul>

私はこれを間違ってやっているのですか?または、場所と写真へのユーザーのオブジェクト参照がバインディングを台無しにしている可能性がありますか?

4

1 に答える 1

18

私はこれを間違ってやっているのですか?

はい。JSONコールバックで上書きobservableArrayしているため、破棄されます。

$.getJSON(baseUri, function (data) {
    self.users = data;
});

一般に、ノックアウトオブザーバブルは次のように割り当てられます。

$.getJSON(baseUri, function (data) {
    self.users(data.$values);
});

あなたの場合、はそれ自体data.$valuesではなく実際の配列を含んでいるように見えることに注意してください。data

これはあなたのケースではうまくいくでしょうが、ノックアウトを最大限に活用していません。

マッピングプラグインは、まさにこの場合のために作成されました。複雑なオブジェクトを再帰的にトラバースし、そのすべてのプロパティを監視可能に変換し、含まれているすべての配列を監視可能配列に変換します。これにより、オブジェクトの状態をきめ細かく制御できるため、すべての変更を監視できます。

$.getJSON(baseUri, function (data) {
    ko.mapping.fromJS(data.$values, {}, self.users);
});

また、部分的な更新も可能です。サーバーからユーザーのリストを取得し、ビューモデルにすでに半分のユーザーがいると仮定します。マッピングプラグインは、欠落しているものだけをビューモデルに追加し、既存のものに適切な変更を加えることができます。方法を知りたい場合は、ドキュメントの「高度な使用法」セクションをお読みください。


サーバーからユーザーオブジェクトの配列を取得し、マッピングプラグインを使用するとすると、バインディングは次のようになります。

<ul id="update-users" data-bind="foreach: users"> 
     <li> 
            <div><div class="item">User ID</div>
                <input type="text" data-bind="value: UserId" />
            </div>                 
            <div><div class="item">Name</div>
                <input type="text" data-bind="value: Name" />
            </div>
            <ul class="photos" data-bind="foreach: Photos.$values">
              <!-- ... -->
            <ul>
     </li> 
</ul>

一般的に、@GregSmithのコメントは正しいです。オブジェクトキーのをなくそう$とすると、ある時点でノックアウトの特別な変数と衝突する可能性があります。たとえば、それらをアンダースコアに安全に置き換えることができます。

$idもっと一般的な注意として、私があなたなら、JSONの/概念全体を取り除こうとし$valuesますが、それは何の目的にも役立たないようです:

[
    {
        "Locations": [],
        "Photos": [],
        "UserId": 1,
        "Name": "Test User"
    }
]
于 2012-11-18T10:34:12.643 に答える