最初に
世間はAngular2で盛り上がっているのにlinkの話かーいって感じですが、directive内でDOM操作したい、jQuery使いたいとかまだニーズあるよね、ということで実装してみました。
調べ方も含めてご参考までに…。
やりたいことは、AngularJS Directiveの処理順を網羅してみた:処理中にjQueryで要素を追加したらどーなるのの、k-cパターンです。
k-c: pre-link内でjQuery#append()
version
- Angular 1.5
- TypeScript 1.8
定義ファイルを読む
interface IDirective
interface IDirective {
compile?: IDirectiveCompileFn;
controller?: any;
controllerAs?: string;
/**
* @deprecated
* Deprecation warning: although bindings for non-ES6 class controllers are currently bound to this before
* the controller constructor is called, this use is now deprecated. Please place initialization code that
* relies upon bindings inside a $onInit method on the controller, instead.
*/
bindToController?: boolean | Object;
link?: IDirectiveLinkFn | IDirectivePrePost;
multiElement?: boolean;
name?: string;
priority?: number;
/**
* @deprecated
*/
replace?: boolean;
require?: string | string[] | {[controller: string]: string};
restrict?: string;
scope?: boolean | Object;
template?: string | Function;
templateNamespace?: string;
templateUrl?: string | Function;
terminal?: boolean;
transclude?: boolean | string | {[slot: string]: string};
}
link?: IDirectiveLinkFn | IDirectivePrePost;
となっているので、linkにはIDirectiveLinkFn かIDirectivePrePostのInterfaceを使えばいいみたいです。
interface IDirectiveLinkFn / IDirectivePrePost
interface IDirectiveLinkFn {
(
scope: IScope,
instanceElement: IAugmentedJQuery,
instanceAttributes: IAttributes,
controller: {},
transclude: ITranscludeFunction
): void;
}
interface IDirectivePrePost {
pre?: IDirectiveLinkFn;
post?: IDirectiveLinkFn;
}
IDirectivePrePostでpre/postにそれぞれIDirectiveLinkFnを継承していますね。
というわけで、IDirectiveを継承したカスタムdirectiveにIDirectivePrePostを継承させたlinkを作成しましょう。
蛇足:interface IDirectiveCompileFn
interface IDirectiveCompileFn {
(
templateElement: IAugmentedJQuery,
templateAttributes: IAttributes,
/**
* @deprecated
* Note: The transclude function that is passed to the compile function is deprecated,
* as it e.g. does not know about the right outer scope. Please use the transclude function
* that is passed to the link function instead.
*/
transclude: ITranscludeFunction
): IDirectivePrePost;
}
IDirectiveCompileFnはIDirectivePrePostを返しています。
書いてみた
module myDirectivesModule {
export class myDirective implements ng.IDirective{
// TODO IDirectiveを参考に必要なものを定義
// public restrict: string;
// public …
constructor() {
this.init();
}
public static Factory(): ng.IDirectiveFactory {
"ngInject";
var directive = () => {
return new myDirective();
}
return directive;
}
// ここ!!
public link: ng.IDirectivePrePost = {
pre: ($scope: ng.IScope, $element: ng.IAugmentedJQuery, $attrs: ng.IAttributes): void => {
// prelinkで実行したい処理
},
post: ($scope: ng.IScope, $element: ng.IAugmentedJQuery, $attrs: ng.IAttributes): void => {
// postlinkで実行したい処理
}
}
private init() {
// TODO 初期化
// this.restrict = 'E';
// this.…
}
}
}
var myapp = angular.module("app"); //ng-app="app"
"ngInject";
myapp.directive('myCustomDirective', myDirectivesModule.myDirective.Factory());
<html lang="ja" ng-app="app">
//・・・
<my-custom-directive></my-custom-directive>
//・・・
</html>
- "ngInject";:gulp-ng-annotate用の定義です。
感想
TypeScriptは定義ファイルみたら何とかなるー…かもヽ( ´ ∇ ` )ノ