2012-12-20 18 views
5

私はKnockoutJSを使用してobservableArrayobservableArrayにあるobservableを購読しようとしています。だから、私のViewModelはobservableArrayでobservableを購読するには

function viewModel() { 
    // private properties 
    var self = this; 

    // public properties 
    self.movies = ko.mapping.fromJS([]); 

    // subscriptions 
    self.movies.UserMovies.Rating.subscribe(function(newValue) { 
     console.log(newValue); 
    }); 
} 

movies observableArrayは、一度マッピング・プラグインから移入次のようになります...

[{ 
    Id: 1, 
    Title: 'Movie1', 
    Year: 2010, 
    UserMovies: [{ Id: 11, Rating: 3.5, IsWatched: true }] 
},{ 
    Id: 2, 
    Title: 'Movie2', 
    Year: 2010, 
    UserMovies: [{ Id: 4, Rating: 4, IsWatched: true }] 
}] 

私はUserMoviesへのサブスクリプションをセットアップしようとしている...このようになります私はへのサブスクリプションの設定について得ただろうか、エラーメッセージ

TypeError: self.movies.UserMovies is undefined

なって、私の上記のViewModelから、.Ratingけどマッピングプラグインから入力されたとき

+0

配列の詳細な購読を希望する場合は、このプラグインの最新バージョンを使用できます。https://github.com/ZiadJ/knockoutjs-reactor – Ziad

答えて

7

ノックアウトは、配列内でどのアイテムが変更されたかを知るための粒度を提供しません。ちょうど何かが変更されました。項目が追加または削除されるたびに、配列をループする必要があります。

foreachバインディング(ko.utils.compareArrays経由)は、1つの配列を別の配列に変換するための最小操作数を実際に計算するので、DOM要素を再作成する必要はありません。

ko.utils.compareArraysを使用して、アイテムレベルで配列の変更をサブスクライブするメソッドを作成できました。これを利用して、サブスクリプションを管理するselectメソッドを書くことができました。新しいselect方法で

http://jsfiddle.net/MizardX/s9M4z/

、あなたはかなり簡潔にこれを行うことができます:

// Subscribe to items added to the array. The returned 'subscription' will be 
// disposed of, when the item is later removed. 
viewModel.movies.select(function (movie) { 

    // Return the subscription. Same as above. 
    return movie.UserMovies.select(function (userMovie) { 

     // Subscribe to a non-array. The callback will receive the updated value, 
     // instead of the an added item. 
     return userMovie.Rating.select(function (rating) { 

      // Executed each time a rating is updated. 
      console.log(movie.Id(), userMovie.Id(), rating); 
     }); 
    }); 
}); 

を期待通りには追加、更新、および削除を処理します。

+0

これはすばらしい答えです。ありがとうMarkus :) – bflemi3

+0

@ bflemi3削除を処理できないため、以前のバージョンに満足できませんでした。これはより堅牢です。 –

2

は、私はあなたの映画をループしており、それぞれの格付けプロパティを購読すると思います。もちろん

$.each(self.movies(), function(i, movie) { 
    movie.Rating.subscribe(function(newRatingValue){ /* ... */ }) 
}); 

ここdonwsideあなたはまた、配列自体に加入する必要がありますということです、アレイに新しいムービーを追加して、の変更を手動でサブスクライブする場合は、の評価値も使用します。

0
あなたは一種のこの方法であなたの特性を購読することができ

:私はあなたがオブジェクトの内部のものに加入してから行う行うことができたりしないことがありますかわからないんだけど、これが行う

var UserMovies = function (data) { 
     this.Id = ko.observable(); 
     this.Rating = ko.observable(); 
     this.IsWatched = ko.observable(); 
     this.update(data); 
    } 

    ko.utils.extend(UserMovies.prototype, { 
     update: function (data) { 
      this.Id(data.Id || ""); 
      this.Rating(data.Rating || ""); 
      this.Rating.subscribe(function (newValue) { 
       console.log(newValue); 
      }); 
      this.IsWatched(data.IsWatched || ""); 
     } 
    }); 

作業。また、各サブスクリプションがユニークであるかどうか、または1つのRatingの変更がすべてのUserMoviesレーティングサブスクリプションを無効にするかどうかもわかりません。私はそれをテストしていない。私は単一のオブジェクトでのみ使用し、オブジェクトの配列では使用しませんでした。

関連する問題