查看代码:
<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)和Chrome(17)中按预期工作,但不是FF(10.0.2)。我基本上试图做一个类似于GitHub问题标签的颜色选择器。视图呈现一组单选按钮,您可以单击以选择颜色。选中广播后,我会向父selected
添加class
css <li>
。 css类会在<li>
上显示一个复选标记图标。
在Firefox中,选定的css类仅在用户完成并至少检查一次每个单选按钮后应用。我调试并发现这是因为在self.Color
闭包中计算BackColorOption
计算的observable的方式。在第一次检查无线电之前,typeof(self.Color) == 'function'
评估为真。但是在检查之后,typeof(self.Color) == 'string'
的计算结果为true。
根据Firebug和Chrome的js调试器,此typeof(self.Color)
行为是相同的。但是FF中的问题是因为self.Selected
闭包中BackColorOption
计算的observable中的这一行:
return backColor.toLowerCase() == self.Color;
Chrome&amp;即使self.Color
是函数而不是字符串,IE仍然返回true。但Firefox没有。当self.Color
是函数时,它返回false。这就是为什么在将css类添加到<li>
之前必须至少检查一次每个无线电并显示图标的原因。
我对淘汰赛仍然有点新意,可能不适当地将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 :(得分:2)
KO中的value
绑定对于单选按钮和复选框并不是很理想。在您的情况下,您需要单选按钮具有value
属性,以便在您单击它们时,该值可用于更新TestViewModel.BackColor
可观察对象。
通常使用单选按钮,您不希望在呈现html后更改value
属性(如果有的话)。
所以,我已经使用value
绑定将html模板改为使用attr
绑定(html属性)。现在只需设置单选按钮的value
html属性即可。然后,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;
});