有没有添加“全局”自定义绑定?例如,我希望为绑定的每个元素触发绑定,而不必将绑定添加到data-bind
属性。可以把它想象成在数据绑定过程中某个时候触发的初始化器。
我真正想要做的是:当一个新模型添加到observableArray
时,我想自动关注新模型的第一个input
,以便用户可以立即开始输入。我认为这不适用于任何现有的绑定。
ko.bindingHandlers.attach = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
valueAccessor().boundElements.push(element);
}
};
这很有效,但我不想在每个绑定元素上都做data-bind="attach: $data"
。是否有任何方法告诉KO在元素上有另一个绑定时始终使用attach
绑定。
注意:写完之后我想我已经决定采用手动方法,但我仍然想知道这是否可行。
答案 0 :(得分:2)
这个答案具体是关于在添加新模型时如何聚焦视图的第一个input
,因为我建议的这个技术与你的完全不同。
我在最近的一个项目中有同样的要求,基本上通过在我的视图模型firstHasFocus
中包含一个observable来解决它。每当该视图模型变为活动状态时,就像切换“标签”时一样,我将firstHasFocus
设置为true
。在视图中,第一个input
使用hasfocus
绑定到该可观察对象。
这是我的代码中的示例,它响应向导类型界面中的“下一步”按钮。它切换到下一步,如果这是当前最后一步,它会聚焦第一个输入。
this.goNext = function() {
if (this.isNextAvailable()) {
var newIndex = this.currentStepIndex() + 1;
this.setCurrentStep(this.steps()[newIndex], newIndex);
if (!this.isNextAvailable()) {
this.currentStep().firstHasFocus(true);
}
}
};
为了确保firstHasFocus(true)
始终更新绑定,它被定义为始终通知:
this.firstHasFocus = ko.observable(false).extend({notify: 'always'});
每个步骤都有一个相应的视图,可以包含对firstHasFocus
的绑定。
<h1>Select the Station Info Columns</h1>
<form>
<label for="stationColumn">Station Name</label>
<select id="stationColumn" name="stationColumn" data-bind="
options: data.headerVarNames, optionsCaption: '----',
value: data.stationHeaderName, valueUpdate: 'afterkeydown',
setfocus: firstHasFocus"></select>
<label for="siteColumn">Site Name</label>
<select id="siteColumn" name="siteColumn" data-bind="
options: data.headerVarNames, optionsCaption: '----',
value: data.siteNameHeaderName"></select>
...
我正在使用自定义绑定setfocus
,而不是标准hasfocus
,因为您不希望调用blur
。这是我的setfocus
绑定:
ko.bindingHandlers.setfocus = {
init: function(element, valueAccessor) {
var modelValue = valueAccessor();
if (!ko.isWriteableObservable(modelValue)) {
throw new Error('setfocus must be used with a writable observable');
}
var writeValue = function(event) {
var modelValue = valueAccessor(),
valueToWrite = element.ownerDocument.activeElement === element;
if (event.type == 'focusin' && !valueToWrite)
element.focus();
else if (valueToWrite != modelValue())
modelValue(valueToWrite);
};
ko.utils.registerEventHandler(element, "focus", writeValue);
ko.utils.registerEventHandler(element, "focusin", writeValue); // For IE
ko.utils.registerEventHandler(element, "blur", writeValue);
},
update: function(element, valueAccessor) {
var value = valueAccessor()(); // access and unwrap observable
setTimeout(function() {
if (value && element.offsetWidth && element.offsetHeight && document.activeElement && document.activeElement != element) {
element.focus();
ko.utils.triggerEvent(element, "focusin"); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
}
});
}
};
答案 1 :(得分:0)
通常,您的视图模型不应该需要访问DOM元素(这是绑定的用途)。但有一种方法可以做到这一点,它被称为自定义绑定提供程序。这还没有正式记录,但它在Ryan Niemeyer's blog上有一些细节。
因此,您可以通过以下方式修改绑定提供程序以添加此行为:
var origNodeHasBindings = ko.bindingProvider.instance.nodeHasBindings,
origGetBindings = ko.bindingProvider.instance.getBindings;
ko.bindingProvider.instance.nodeHasBindings = function(node) {
return (node.nodeType === 1) || origNodeHasBindings(node);
};
ko.bindingProvider.instance.getBindings = function(node, bindingContext) {
var bindings = origGetBindings.call(this, node, bindingContext) || {};
bindings.attach = bindingContext.$data;
return bindings;
};