0

とにかく「グローバル」カスタムバインディングを追加する方法はありますか? たとえば、バインディングをdata-bind属性に追加することなく、バインドされているすべての要素に対してバインディングを起動したいと考えています。これは、データ バインディング プロセス中に起動する初期化子と考えてください。

私が本当にやりたいことはこれです: 新しいモデルが に追加されたとき、ユーザーがすぐに入力を開始できるようobservableArrayに、新しいモデルの最初のモデルにオートフォーカスしたいと考えています。inputこれが既存のバインディングのいずれでも機能するとは思いませんでした。

ko.bindingHandlers.attach = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        valueAccessor().boundElements.push(element);
    }
};

data-bind="attach: $data"それは機能しますが、バインドされたすべての要素に対して行う必要はありません。attach要素に別のバインディングがある場合は常にそのバインディングを使用するように KO に指示する方法はありますか?

注:これを書いた後、とにかく手動の方法を使用することに決めたと思いますが、これが可能かどうかを知りたいです。

4

2 に答える 2

2

この回答は、特に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、標準の代わりにカスタムバインディングを使用しています。これが私のバインディングです:hasfocusblursetfocus

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
            }
        });
    }
};
于 2013-04-25T23:41:46.317 に答える