次のように、Knockout.js 用の非常に単純な Bootstrap Typeahead バインディング (jsFiddle)があります。
ko.bindingHandlers.typeahead = {
init: function (element, valueAccessor) {
var $e = $(element),
source = valueAccessor();
$e.typeahead({
source: source,
minLength: 0
});
},
};
使い方は簡単です:
<input data-bind='typeahead: source, value: item,
valueUpdate: "afterkeydown"' />
バインディングはjsFiddleで期待どおりに機能します。ただし、RequireJS をロードすると、常に期待どおりに動作するとは限りません。Knockout と jQuery が並行してロードされているため、競合状態が発生しているようです。
バインドされた入力要素のイベント ハンドラーを見ると、change
jQuery がハンドラーである場合、バインドは期待どおりに機能します。Knockout がchange
イベントのハンドラーである場合、たとえば、「alp」と入力し、Typeahead が「Alpha」を提案し、Typeahead ドロップダウン リストから「Alpha」を選択すると、<input>
要素には選択されたテキスト (「Alpha」) が表示されます。 )、ただし、バインドされたオブザーバブルは「alp」になります。
現在のシステムでは、Typeahead バインディングは指定されたオブザーバブルを直接変更できないため、パス{ source: src, observable: item }
しても問題は解決しません。この Typeahead バインディングの役割は、バインドされた入力領域のコンテンツを更新することだけです。
「keydown」、「keypress」、「keyup」など、バインドから関連するイベントをトリガーすることを実験しましたが、明らかな理由から、これは非常に回復力のあるオプションではありません。
この問題は RequireJS の不確定性に関連していると思われます。Typeahead プラグインが機能するかどうかは、jQuery または Knockout が最初に読み込まれたかどうかによって決まります。特に、この問題は、RequireJS を使用して jQuery を Knockout の依存関係にする (つまり、最初に jQuery をロードする) ことで解決されるようですshim
。
requirejs.config({
shim: {
knockout: { deps: ['jquery'] },
}
});
これは奇妙に思えます。ここで何が起こっているのか、そしてこれが問題の合理的な解決策であるかどうかをよりよく理解したいと思います。つまり、ここで根本的な問題に実際に対処しているのか、それとも Knockout または jQuery の後続のバージョンで問題が発生する可能性があるのか .
どんな考えにも感謝します。
編集
たとえば、次のようにインラインでスクリプトを順番にロードすることで、問題を簡単に再現できます。
<script src='knockout.js'></script>
<script src='jquery.js'></script>
上記の順序では、プラグインは失敗します。それ以外の場合は、期待どおりに機能します。
いずれにせよ、RequireJS 構成は次のようになります。
requirejs.config({
baseUrl: "/script",
shim: {
knockout: { deps: ['jquery'] }, # remove this for race condition
}
});
main
hasの簡略化されたバージョンで、Knockout ハンドラーを定義しますrequire(['jquery', 'knockout', 'bindings'], ...)
。ファイルは実質的bindings
に.bindings.js
define(['knockout', 'jquery'], ...)
この場合、問題は RequireJS ではなく、スクリプトの順序にあります。