そもそもAngularUI-Select2の単体テストすらIE8では動作しない。かたやSelect2単体はIE8でも普通動く。
じゃあもうSelect2を自分でディレクティブにしてしまえと思った。
ディレクティブを作るのは再利用できるようにしたりとか、ちゃんとやるとコード量も増えてなかなか難しいけど、使用方法なんかをある程度決めうちしてしまえば割と簡単にできる。ただディレクティブのスコープ周りとかapply、parse周辺は本当にこれで良いのかやや不安なので、より良い方法があるなら是非ご教授いただきたい。
コードは以下の通り。
angular.module('tag',[]).directive("tag", function($parse) { return { restrict : 'A' ,require:['ngModel'] ,link : function(scope, element, attr) { //選択候補 var tags = []; var result = $parse(attr.ngModel); //Select2の作成対象 var input = element.children('input'); //Select2を作成する。idは比較するときの対象なので //textにしておかないと、選択候補と同じタグを新たに作成できてしまう input.select2( { tags:function(){return tags} ,id:function(i){return i.text} }); input.on("change",function() { //選択結果を渡す result.assign(scope,input.select2('data')); //変更結果を適用する if(scope.$$phase) { scope.$eval(attr.ngModel); } else { scope.$apply(attr.ngModel); } }); //選択候補の監視 scope.$watch(attr.tag,function(newValue) { tags = newValue; },true); //選択状態の監視 scope.$watch(attr.ngModel,function(newValue) { input.select2("data",newValue); },true); } ,template : '<input type="text" />' }; });
これを<div tag="tags" ng-model="selected">みたいな感じで使う。
本当は<input tag=...>みたいに出来た方がスマートな感じで、AngularUIではそうしているのだけど、Select2が追加するタグのせいでng-showなんかを使うためには一階層上に付けなくてはならなかったりして、結局不便になっているのでこうした。