ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

【AngularJS1.5.x】directiveのtemplateにfilterを引数で渡したい

スポンサードリンク

渡したかった。

  • index.html
<first-directive main="main.myDirective" filter-name="number"></first-directive>
  • app.js
    .directive('firstDirective', ['$log', 'FigureService', function ($log, FigureService) {
        return {
            restrict: 'E',
            scope: {
                directiveMain: '=main',
                filterName: '=filterName'
            },
            controller: 'Main',
            template: '<ul>' +
                      '    <li ng-bind="directiveMain.triangle + \':三角形\'"></li>' +
                      '    <li ng-bind="directiveMain.circle + \':円\'"></li>' +
                      '    <li ng-bind="directiveMain.trapezoid + \':台形\'"></li>' +
                      '    <li>{{directiveMain.circle | filterName}}</li>' +
                      '</ul>',
            link: function(scope, element, attrs, controller) {
            }
        }
    }])

エラーでした。

Error: $injector:unpr Unknown Provider

Unknown provider: filterNameFilterProvider <- filterNameFilter

うーむ。filterとして認識されていない?

            template: '<ul>' +
                      '    <li ng-bind="directiveMain.triangle + \':三角形\'"></li>' +
                      '    <li ng-bind="directiveMain.circle + \':円\'"></li>' +
                      '    <li ng-bind="directiveMain.trapezoid + \':台形\'"></li>' +
                      '    <li>{{directiveMain.circle | filter:filterName}}</li>' +
                      '</ul>',

filter:っていう文字を追加

Error: filter:notarray Not an array

Expected array but received: 314.1592653589793

「配列希望だけど、違うよ」って感じ。何故だ。

次は普通に使ってみる

                      '    <li>{{directiveMain.circle | number}}</li>' +

これは動いた。

うーむ。。。

30分経過

だんだん英語の記事の引っぱりかたがわかってきた。

「angularjs filter argument」とかで検索してしまうと、「angularjsのfilterで引数の渡し方」みたいな記事しか引っぱってこない。

「how can i ~」とか「how to ~」とかつけると、「やり方」=> 手順っぽい記事を探してくれる。

「how to pass filter to a directive」とかで検索するとマッチした。(+ in angularjs とか書くと完璧かも)

stackoverflow.com

で、directivescopeで渡したいfilterは、templateで実行することができないっぽい。

実現できた書き方としてこんな感じ。

    .directive('firstDirective', ['$log', 'FigureService', '$filter', function ($log, FigureService, $filter) {
        return {
            restrict: 'E',
            scope: {
                directiveMain: '=main',
                filterName: '=filterName'
            },
            controller: 'Main',
            template: '<ul>' +
                      '    <li ng-bind="directiveMain.triangle + \':三角形\'"></li>' +
                      '    <li ng-bind="directiveMain.circle + \':円\'"></li>' +
                      '    <li ng-bind="directiveMain.trapezoid + \':台形\'"></li>' +
                      '    <li><input type="text" ng-model="directiveMain.trapezoid" ng-blur="myBlur()" ng-model-options="{updateOn: \'blur\'}"></li>' +
                      '</ul>',
            link: function(scope, element, attrs, controller) {
                // directiveがインスタンス生成される度に実行される
                $log.info(scope);
                $log.info(element);
                $log.info(attrs);
                $log.info(controller);

                // Serviceを仕様して、directiveのscopeを変更
                // controllerとbindするとmodelがシェアされる
                scope.directiveMain.triangle = FigureService.triangle(10, 5);
                scope.directiveMain.circle = FigureService.circle(10);
                scope.directiveMain.trapezoid = $filter(scope.filterName)(FigureService.trapezoid(1320, 5, 3)); // ここの部分

                scope.myBlur = function() {
                    console.log($filter(scope.filterName)(scope.directiveMain.trapezoid));
                };
            }

linkで実行すれば良い。

だがしかし、これだと初回の実行だけで、値を変えた場合はfilterが実行されない。

なので、常に実行する場合はeventの発火を監視して、filterを実行すればいいんじゃないかなと思う。