唯一ID
假设我有knockout.js模板是这样的:唯一ID
<script type="text/html" id="mytemplate">
<label for="inputId">Label for input</label>
<input type="text" id="inputId" data-bind="value: inputValue"/>
</script>
如果我呈现我最终具有相同id多个输入页面上的几个地方这个模板(和与值相同的几个标签具有相同的),这具有不良后果。尤其是,所有依赖于ID的代码可能无法正常工作(在我的例子中,我使用了jquery.infieldlabel插件,它被多个输入与相同的ID混淆)。我现在解决这个问题的办法是我加的独特id属性,我绑定到模板的模型:
<script type="text/html" id="mytemplate">
<label data-bind="attr: {for: id}>Label for input</label>
<input type="text" data-bind="attr: {id: id}, value: inputValue"/>
</script>
这工作,但因为我要在我的模型这种人工id属性这不是很优雅这不是用于其他任何事情。我想知道这里是否有更好的解决方案。
不依赖于字段绑定顺序的替代方法是使绑定对数据本身设置id
属性,该属性需要是可观察的。
ko.bindingHandlers.uniqueId = {
init: function(element, valueAccessor) {
var value = valueAccessor();
value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);
element.id = value.id;
},
counter: 0,
prefix: "unique"
};
ko.bindingHandlers.uniqueFor = {
init: function(element, valueAccessor) {
var value = valueAccessor();
value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);
element.setAttribute("for", value.id);
}
};
你会用它喜欢:
<ul data-bind="foreach: items">
<li>
<label data-bind="uniqueFor: name">Before</label>
<input data-bind="uniqueId: name, value: name" />
<label data-bind="uniqueFor: name">After</label>
</li>
</ul>
样品:http://jsfiddle.net/rniemeyer/JjBhY/
增加一个属性,以可观察到的功能的好处是,当你把它变成JSON传送回服务器,那么它就会自然消失,因为可观察值将变成它的解包值。
我做了这样的事情在过去的:
ko.bindingHandlers.uniqueId = {
init: function(element) {
element.id = ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);
},
counter: 0,
prefix: "unique"
};
ko.bindingHandlers.uniqueFor = {
init: function(element, valueAccessor) {
var after = ko.bindingHandlers.uniqueId.counter + (ko.utils.unwrapObservable(valueAccessor()) === "after" ? 0 : 1);
element.setAttribute("for", ko.bindingHandlers.uniqueId.prefix + after);
}
};
你会使用他们喜欢的:
<ul data-bind="foreach: items">
<li>
<label data-bind="uniqueFor: 'before'">Before</label>
<input data-bind="uniqueId: true, value: name" />
<label data-bind="uniqueFor: 'after'">After</label>
</li>
</ul>
所以,它只是不断增加自身的ko.bindingHandlers.uniqueId.counter
绑定状态。然后,uniqueFor
绑定只需知道是否在字段之前或之后知道如何获得正确的id。
样品在这里:http://jsfiddle.net/rniemeyer/8KJD3/
如果您的标签不靠近他们的领域(也许在一个表中的单独行每个标签之前势必多个输入),那么你就需要考虑不同的策略。
我在想沿着这些线路的东西太多,而且必定会在我的情况下工作,但我不喜欢这个解决方案是,它取决于标签呈现的顺序。谢谢你的代码,但它绝对是其中一个选项。 – 2012-02-10 20:07:11
如果订单是一个问题,那么这里是另一种选择:http://jsfiddle.net/rniemeyer/JjBhY/。这是相似的,但是绑定会对可能观察到的内容设置“id”属性。无论绑定是什么,它首先会更新id。关于在observable函数上设置“id”属性的好处是,当它变成JSON时它将会消失,因为您只剩下可观察值的解包值。 – 2012-02-10 20:23:26
谢谢,这正是我一直在寻找的!你介意发布这个答案,以便我能接受它吗? – 2012-02-10 20:50:52
我无法回复所选答案,但是我有一个支持每个输入值多个唯一ID的代码的增强版本。这是对我在http://drewp.quickwitretort.com/2012/09/18/0博客并在此重复:
ko.bindingHandlers.uniqueId = {
/*
data-bind="uniqueId: $data" to stick a new id on $data and
use it as the html id of the element.
data-which="foo" (optional) adds foo to the id, to separate
it from other ids made from this same $data.
*/
counter: 0,
_ensureId: function (value, element) {
if (value.id === undefined) {
value.id = "elem" + (++ko.bindingHandlers.uniqueId.counter);
}
var id = value.id, which = element.getAttribute("data-which");
if (which) {
id += "-" + which;
}
return id;
},
init: function(element, valueAccessor) {
var value = valueAccessor();
element.id = ko.bindingHandlers.uniqueId._ensureId(value, element);
},
};
ko.bindingHandlers.uniqueFor = {
/*
data-bind="uniqueFor: $data" works like uniqueId above, and
adds a for="the-new-id" attr to this element.
data-which="foo" (optional) works like it does with uniqueId.
*/
init: function(element, valueAccessor) {
element.setAttribute(
"for", ko.bindingHandlers.uniqueId._ensureId(valueAccessor(), element));
}
};
现在你可以有多个标记复选框一条记录自动IDS:
<li data-bind="foreach: channel">
<input type="checkbox" data-which="mute" data-bind="uniqueId: $data, checked: mute">
<label data-which="mute" data-bind="uniqueFor: $data">Mute</label>
<input type="checkbox" data-which="solo" data-bind="uniqueId: $data, checked: solo">
<label data-which="solo" data-bind="uniqueFor: $data">Solo</label>
</li>
我第二。但是,我是否会感到恼火,并且要求就一个稍微复杂一些的问题寻求建议 - 在那里你有一对无线电,例如,作为标签的“是”和“否”,每一个绑定回单个布尔可观察值,例如, “活跃”。此刻,所有4个元素--2个收音机和2个标签 - 都获得相同的ID。无线电对本身出现多次,所以我使用Knockout绑定为每个对生成一个唯一的名称属性,所以我需要能够将当前对的特定名称前缀到ID。 – 2012-07-16 03:55:24
您也可以使用data-bind =“attr:{for:'status_'+ $ index}”和data-bind =“attr:{id:'status_'+ $ index}”为唯一ID – viperguynaz 2013-07-26 19:14:00
您也可以使用data-bind =“attr:{for:'status_'+ $ index}”和data-bind =“attr:{id:'status_'+ $ index}”。 $ index引用当前数组项目的从零开始的索引。 $ index是一个可观察值,只要项目的索引发生更改(例如,如果将项目添加到阵列或从阵列中删除项目),它就会更新。 – viperguynaz 2013-07-26 19:27:44