2012-03-13 57 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' /> 

视图模型代码:

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)和Chrome(17),但没有FF(10.0.2)。我基本上试图做一个类似于GitHub的问题标签的颜色选择器。该视图呈现一组单选按钮,您可以点击选择一种颜色。当收音机被检查时,我将selected css class添加到父母<li>。 css类会在<li>上出现复选标记图标。

在Firefox中,所选的css类仅在用户完成并检查每个单选按钮后至少应用一次。我调试并发现,这是因为在BackColorOption闭包中计算的self.Color计算可观察值。在第一次检查收音机之前,typeof(self.Color) == 'function'的计算结果为true。但是,在检查之后,typeof(self.Color) == 'string'的计算结果为true。

typeof(self.Color)根据Firebug和Chrome的js调试器的行为是相同的。然而,在FF的问题,因为这条线在self.SelectedBackColorOption封闭计算观察到的:

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

铬& IE仍然返回true,即使self.Color是一个函数,而不是一个字符串。但Firefox不。当self.Color是一个函数时,它返回false。这就是为什么在将css课程添加到<li>之前至少要检查一次收音机,并且出现图标。

我还是有点新的淘汰赛,并可能不适当调用viewmodel属性作为一个函数时应该。我仍然有点不清楚何时使用括号,何时忽略它们。是否有另一种方法我应该写self.Selected计算可观察,这取决于self.Color计算可观察(在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 2012-03-13 18:00:43

+0

这里是一个小提琴:http://jsfiddle.net/JUKGh/2/ – danludwig 2012-03-13 18:15:41

回答

2

在KO中的value绑定对于单选按钮和复选框并不是很理想。在你的情况下,你需要你的单选按钮具有value属性,以便当你点击它们时,该值可以用来更新你的可观察值。

通常使用单选按钮,一旦呈现html,您不希望value属性更改(如果曾经)。

所以,我已经改变了你的html模板使用value绑定来代替使用attr绑定(html属性)。现在,您只需设置单选按钮的HTML属性value即可。 checked绑定然后保持您的TestViewModel.BackColor可观察与任何value是检查的单选按钮同步。

看到这个小提琴: 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 2012-03-13 18:22:54