2013-03-01 6 views
16

私は単純な修正でなければなりません。ネストしたビューモデルでknockout.jsを使用していますが、削除機能が正しく動作していないことを除いて、すべてがうまく見えます。これは正しくバインドされているようですが、削除をクリックすると起動しません。ノックアウトネストされたビューモデル

なぜネストされたビューモデルですか?長い話ですが、本質的には1ページになるために多くのものが必要です!だからここ

はコードです:

HTML

<section class="mini-form-container"> 
    <form data-bind="submit: repeatGuest.addDate"> 
     <input type="date" data-bind="value: repeatGuest.previousStay"/> 
     <button type="submit" class="button-secondary ">Add date</button> 
    </form> 
    <div data-bind="foreach: repeatGuest.dates, visible: repeatGuest.dates().length > 0"> 
     <div> 
      <input data-bind="value: date" disabled="disabled" /> 
      <a data-bind="click: $parent.removeDate">Remove</a> 
     </div> 
    </div> 
</section> 

<section> 
    <div data-bind="text: ko.toJSON($data)"></div> 
</section> 

Javascriptを

function RepeatGuest() { 
    /// <summary>Child View Model</summary> 
    this.dates = ko.observableArray(); 
    this.previousStay = ko.observable(); 
} 

RepeatGuest.prototype.addDate = function() { 
     var self = this.repeatGuest; 
     if (self.previousStay()) { 
      self.dates.push({ 
       date: self.previousStay() 
      }); 
     } 
    }; 

RepeatGuest.prototype.removeDate = function (date) { 
    this.dates.remove(date); 
} 

function ViewModel() { 
    var self = this; 
    self.repeatGuest = new RepeatGuest(); 
} 
ko.applyBindings(new ViewModel()); 

そして、ここでは私のバイオリンです:http://jsfiddle.net/6Px4M/2/

では、なぜ私の削除関数が起動しないのですか?

可能性のある側の質問:ノックアウトで取るために間違ったパスは、ネストされたビューモデルにあり、これに関する多くの情報に存在していないようですか?

答えて

23

一つはwithバインディングを使用することです。

<div data-bind="with: repeatGuest"> 
    ... 
</div> 

さて、スコープがあなたのrepeatGuestであり、あなたがそのプロパティに直接バインドすることができます:あなたが行うことができます。

remove関数の問題は、thisの値に関係し、そのときは$parentとなります。関数は、現在のスコープと等しい値thisで実行されます。 remove関数がバインドされている場合、スコープはdate配列内のオブジェクトの1つです。

これを処理する一般的な方法は、あなたの関数が常にthisの正しい値を使用するようにバインドされていることを確認することです。

<a data-bind="click: $parent.repeatGuest.removeDate.bind($parent.repeatGuest)">Remove</a> 

より良いオプションは、あなたのRepeatGuestコンストラクタで、ビューモデルにバインドすることです:

this.removeDate = this.removeDate.bind(this); 

これは、実装が生きることを可能にするようにこれは、結合(非常に醜い)で行うことができますプロトタイプ上に置き、それぞれのインスタンス上でそれを上書きします。正しい値はthisです。また、プロトタイプに入れない場合は、var self = this;パターンを使用し、ハンドラでselfを使用できます。

http://jsfiddle.net/cNdJj/

+0

私は 'var self = this'パターンが好きです。関数をバインドするのを覚えるよりも、 'self'だけを使うほうが簡単です。それはまた、よりきれいに見えます。 – Tyrsius

+0

この良いもの、私から+1、しかし、彼はプロトタイプに貼り付けて以来、機能が実行されていなかったより根本的な問題があった。彼があなたのすべての措置をたどっていれば解決されるだろうが。 –

+0

@Tyrsius - 私はあなたがまだプロトタイプに関数の実装を置く方法を示すことを試みていました。 'self'は良いパターンです。 –

4

結合が間違ったプロトタイプで機能にアクセスできません。あなたはviewModelにバインドしていますが、今はRepeatGuestオブジェクトにバインドしていません。あなたはローカル関数として設定している場合、それが動作

:このようなネストされたモデルで作業するための最良の方法の

http://jsfiddle.net/6Px4M/3/

function ViewModel() { 
    var self = this; 
    self.repeatGuest = new RepeatGuest(); 
    self.removeDate = function (date) { 
     self.repeatguest.dates.remove(date); 
    } 
} 
+0

ああ、これは元々私が持っていた方法です。しかし、私のviewModelは大規模になり、私はそれをリファクタリングしようとしていました。ビューモデルからremove関数を取得する他の方法はありますか? –

+0

もちろん、あなたはいつでもそれを取り出して、関数名に 'self.removeDate'をセットするだけで済みます。 –

+1

@ RPNiemeyerのソリューションはより完全です。 –

関連する問題