この回答は、特にinput
、新しいモデルが追加されたときにビューの最初にフォーカスする方法に関するものです。これを行うために私が提案する手法は、あなたのものとはまったく異なるためです。
私は最近のプロジェクトでこれと同じ要件を持っていましたfirstHasFocus
. 「タブ」を切り替えるときのように、そのビューモデルがアクティブになるときはいつでも、私はに設定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
}
});
}
};