2012-03-13 8 views
0

コード:ノックアウトバインディングを間違って行っていますか?

<ul data-bind="foreach: BackColorOptions"> 
    <li data-bind="css: { selected: Selected }"> 
     <label> 
      <input type="radio" name="BackColorOption" 
       data-bind="value: Color, checked: $root.BackColor" /> 
     </label> 
    </li> 
</ul> 
@{ 
    var jsonModel = new System.Web.Script.Serialization. 
     JavaScriptSerializer().Serialize(Model); 
} 
<input type="hidden" id="JsonModel" value='@jsonModel' /> 

のviewmodelコード:

var initialData = $.parseJSON($('#JsonModel').val()); 

function BackColorOption(data, parent) { 
    var self = this; 
    self.parent = parent; 
    self.Text = ko.observable(data.Text); 
    self.Color = ko.computed(function() { 
     return '#' + self.Text().toLowerCase(); 
    }); 
    self.Selected = ko.computed(function() { 
     var backColor = self.parent.BackColor(); 
     if (backColor) { 
      return backColor.toLowerCase() == self.Color; 
     } 
     return false; 
    }); 
} 

function TestViewModel() { 
    var self = this; 

    self.BackColor = ko.observable(initialData.BackColor); 

    var mappedBackColorOptions = $.map(initialData.BackColorOptions, 
     function (item) { 
      return new BackColorOption(item, self); 
     } 
    ); 
    self.BackColorOptions = ko.observableArray(mappedBackColorOptions); 

} 

ko.applyBindings(new TestViewModel()); 

モデルコード:予想通り

string BackColor { get; set; } 
SelectListItem[] BackColorOptions 
{ 
    get 
    { 
     return new[] 
     { 
      new SelectListItem{Text = "cc0000"}, 
      new SelectListItem{Text = "ff9900"}, 
      new SelectListItem{Text = "dddd33"}, 
      new SelectListItem{Text = "009900"}, 
      new SelectListItem{Text = "00cccc"}, 
      new SelectListItem{Text = "0066ff"}, 
      new SelectListItem{Text = "9900ff"}, 
      new SelectListItem{Text = "ff00ff"}, 
     }; 
    } 
} 

上記のコードは、IEで動作し( 8)とクロム(17)、しかしそうではないFF(10.0.2)。私は基本的にGitHubの発行ラベルに似たカラーセレクタを実行しようとしています。このビューは、クリックすることで色を選択できる一連のラジオボタンをレンダリングします。ラジオがチェックされると、<li>selected css classを追加します。 cssクラスは、<li>の上にチェックマークアイコンを表示します。

Firefoxでは、選択したcssクラスは、ユーザーが少なくとも1回は各ラジオボタンをチェックして確認した後にのみ適用されます。私はデバッグし、self.Color計算されたobservableがBackColorOptionクロージャで評価される方法が原因であることがわかりました。最初にラジオがチェックされる前に、typeof(self.Color) == 'function'が真と評価されます。しかし、それがチェックされた後、typeof(self.Color) == 'string'は真と評価されます。

このtypeof(self.Color)の動作は、FirebugとChromeのjsデバッガの両方で同じです。しかし、FFでの問題は、BackColorOption閉鎖に観察可能な計算self.Selectedであるため、この行は次のとおりです。self.Colorではなく、文字列の関数である場合でも

return backColor.toLowerCase() == self.Color; 

クローム& IEはまだtrueを返します。しかし、Firefoxはそうではありません。 self.Colorが関数の場合、falseを返します。このため、CSSクラスが<li>に追加される前に、各無線機を少なくとも1回確認する必要があり、アイコンが表示されるのはこのためです。

私はまだノックアウトに新しく、想定していたときにviewmodelプロパティを関数として適切に呼び出さない可能性があります。私はまだ、かっこを使用するとき、およびそれらを省略するときは、少し不明です。私はself.Selected計算されたobservableを書くべき別の方法は、self.Color計算されたobservable(BackColorOptionクロージャで)に依存しますか?

アップデート1

私は、これは次のようにFF 10.0.2の中に仕事を得ることができました:

self.Selected = ko.computed(function() { 
    var backColor = self.parent.BackColor(); 
    var selfColor = self.Color; 
    if (typeof (selfColor) === 'function') 
     selfColor = self.Color(); 
    if (backColor) { 
     return backColor.toLowerCase() === selfColor; 
    } 
    return false; 
}); 

私はノックアウトを戦っているようしかし、これは感じています。それは "ただの仕事"ではないと思いますか?

+0

あなたがこれを実証するためのjsfiddleをノックするだろうか? – madcapnmckay

+0

ここでは謎です:http://jsfiddle.net/JUKGh/2/ – danludwig

答えて

2

KOでのバインディングvalueは、ラジオボタンやチェックボックスにはあまり適していません。状況に応じてラジオボタンにvalue属性が必要です。クリックすると、その値を使用してTestViewModel.BackColorを更新することができます。

通常、ラジオボタンでは、value属性が変更されることはありません。

したがって、バインディング(html属性)を代わりに使用して、valueバインディングを使用するようにhtmlテンプレートを変更しました。これでラジオボタンのhtml属性がvalueに設定されました。 checkedバインドでは、チェックされているラジオボタンのvalueと一致するように、あなたのTestViewModel.BackColorを観測可能な状態に保ちます。

このフィドルを参照してください: http://jsfiddle.net/m2KQ2/

はまた、あなたのBackColorOption関数内の行は、タイプミスがあります

self.Selected = ko.computed(function() { 
    var backColor = self.parent.BackColor(); 
    if (backColor) { 
     return backColor.toLowerCase() == self.Color; //<-- should be Color(); 
    } 
    return false; 
}); 
+0

ありがとうエリック、はい、それは動作します。値バインディングではなく、attrバインディングを使用して値をバインドすることは私には起こりませんでした。あなたは正しいです、私はラジオボタンの値を変更したくありません。あなたのフィドルが関数としてself.Color()を呼び出していることに気づき、それに応じてコードを更新しました。 – danludwig

関連する問題