angular.jsのdirectiveでlistにactiveをつける

bootstrapでよくある縦並びのメニューでactiveクラスをつけるdirectiveをつくってみる

directiveの指定種別

directiveはattribute、element、classの3つで指定できる。デフォルトはattributeなのでclassに変更する必要がある

restrict: 'A' // Attribute <div ng-custom></div>
restrict: 'E' // Element <ng-custom></ng-custom>
restrict: 'C' // Class <div class="ng-custom"></div>

directive名について

directive名はlowercaseで指定してcamelcaseで指定する

directive('ngCustom', function() {
    // これはng-customのdirectiveになる
});

link/compile

詳細な動作はlink/compileで記載。今回はactiveを付けたいのでlink内で判定を記載する

pushstate時のhandling

link/compileで記載するとリロード時には動作するが、pushstateだと動かない。イベントをScopeでWatchする必要がある

できあがり

以上を加味して記載するとこんな感じになるはず。list-group-itemのhrefを引っ張ってきて、それを現在のlocation.hrefと比較してactiveクラスをつけたり消したりしている。

	angular.module('myApp').directive('listGroupItem', function() {
			return {
				restrict:'C',
				link: function($scope, element, attrs) {
					$scope.$on('$routeChangeStart', function() {
						if(attrs.href == location.href) {
							element.addClass('active');
						} else {
							element.removeClass('active');
						}
					});
				}
			};
		}
	);

まとめ

$routeChangeStartのイベントをwatchするということがわかるまで時間がかかったけど、directiveを使って色々できそう。でもこれってカスタマイズし過ぎたら可読性が落ちる諸刃の剣だと思う。決まったところに決まったものを出すだけであれば使えばいいんじゃないかな。