jQuery UI の autocomplete と knockout.js を組み合わせた場合の問題点 †
- [問題] jQuery UI の autocomplete で選択された値が View Model に反映されないときがある
- knockout.js は、通常 change イベントで、<input> の入力内容を View Model に反映する
- jQuery UI の autocomplete で、ユーザが候補からマウスで選択した場合、単に $(input).val() で <input> に値が設定されるだけなので change イベントが発生しない
⇒ jQuery UI の autocomplete でユーザが候補からマウスで選択した場合 View Model が更新されない。困った困った
- [解決策] blur イベントで View Model に反映するように設定すれば良くね?
- リアルタイムの反映は無理でも、<input> からフォーカスが外れた段階で View Model に反映されれば実質的に問題ない
- Clipboard や Drag&Drop もフォーカスが外れた段階で View Model に反映されることになる
サンプルアプリケーション †
ソースコード †
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>knockdown.js Ex10</title>
<link rel="stylesheet" type="text/css" media="screen" href="js/lib/jquery-ui-1.11.3/jquery-ui.min.css">
<script type="text/javascript" charset="UTF-8" src="js/lib/require.js" data-main="js/knockoutExA_init.js"></script>
</head>
<body>
<fieldset>
<legend>未対策</legend>
<input id="tags1" data-bind="value: lang1, valueUpdate: 'afterkeydown'">
⇒ <span data-bind="text: lang1"></span><br/>
マウスで候補を選択すると、選択結果が View Model に反映されない
</fieldset>
<fieldset>
<legend>対策済み</legend>
<input id="tags2" data-bind="value: lang2, valueUpdate: ['afterkeydown', 'blur']">
⇒ <span data-bind="text: lang2"></span><br/>
マウスで候補を選択しても、フォーカスが外れた段階で View Model に反映される
</fieldset>
</body>
</html>
/*
* アプリケーションのイニシャライザ.
*/
require.config({
// Javascript の Base Url
baseUrl: 'js/lib',
// ライブラリのパスの別名を定義する
paths: {
'app': '../',
'knockout' : 'knockout-3.2.0',
// jQuery 1.7〜, Query UI 1.11〜 は AMD に対応
'jquery' : 'jquery-ui-1.11.3/external/jquery/jquery',
'jqueryui' : 'jquery-ui-1.11.3/jquery-ui.min',
},
// AMDに対応してないモジュールを読み込む
shim: {
}
});
require(['knockout', 'app/knockoutExA_vmodel', 'jquery', 'jqueryui', 'domReady!'],
function(ko, vmdl, $) {
ko.applyBindings(new vmdl());
var availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
$( "#tags1" ).autocomplete({
source: availableTags
});
$( "#tags2" ).autocomplete({
source: availableTags
});
}
);
/*
* アプリケーションの View Model.
*/
define(['knockout','jquery'], function(ko,$) {
return function appViewModel() {
var self = this;
self.lang1 = ko.observable();
self.lang2 = ko.observable();
};
});
HTML#Knockout