angular.js directiveのbindToController

2015-06-20T16:45:37+09:00 JavaScript angular.js

参考: AngularJS1.4とbindToController

参考から引用すると

Directiveを自作する時に、コントローラーへ値を引き渡し、バインディングするには$scopeが必要でしたが、これが$scopeいらずで行えるようになりました。ng-controllerのas構文では先行して可能だったことがDirectiveでも可能になったんです。また、1.4では、どの値をバインディングするのか、どの値をバインディングしないのかを明確に定めることができるようになりました。

との事。要はdirectiveで指定されるcontrollerにdirectiveが持つscope等で指定したパラメーター等をcontrollerのプロパティとして伝播し利用する事が1.3からbindToControllerを使って可能になり、1.4からはbindToControllerのパラメーターの設定によりバインディングの設定等が行えるようになったよ的な事かと

っていう事でやってみる

index.html

{% raw %}
<!DOCTYPE html>
<html ng-app="sample">
  <head>
    <script src="angular.js"></script>
    <script src="app.js"></script>
  </head>
  <body>
    <sample-directive num="1" name="'hoge'">
      {{ctrl.num}}: {{ctrl.name}}
    </sample-directive>
  </body>
</html>
{% endraw %}

まぁsample-directiveを作って属性の値をcontrollerに伝播する、そこの内部でcontrollerAsで指定した名前でパラメーターをレンダリングするっていう単純なケース

app.js

function SampleCtrl($timeout, $scope) {
  // directiveから作用したパラメーター値がcontrollerに伝播されてバインディングされる
  // ↑により結果は Object {num: 1, name: "hoge"} となる
  console.log(this);

  /*
  もしdirectiveから渡された値を改変するような場合には$scope.$applyにて処理しなければならない模様

  var self = this;

  $timeout(function() {
    $scope.$apply(function() {
      self.name = 'A';
    });
  });
  */
}

angular.module('sample', [])
  .directive('sampleDirective', function() {
    return {
      restrict: 'E',
      scope: {},
      controller: SampleCtrl,
      controllerAs: 'ctrl',
      bindToController: {
        num: '=',
        name: '='
      },
      transclude: true,
      link: function(scope, elem, attrs, ctrl, transclude) {
        transclude(scope, function(clone) {
          elem.append(clone);
        });
      }
    };
  });

上記でも書いてるように1.3の場合にはscopeに指定しなければならないけど、1.4ならbindToControllerで設定する事が可能なのでそちらで設定してもいい。ハマった点として

  • controller及びcontrollerAsの指定は必須
  • scopeも{}かtrueで指定する必要あり
  • templateとか指定する場合にはtranscludeする必要は無いはず

というような感じ。他にも色々罠がある模様、それに関しては上記の参考資料に記載されているのでそれ読めば良い(2語名なdirectiveを使うと上手く作用しない等)

という感じで合ってるか微妙だけど、directiveから作用するパラメーターをコントローラーに伝播するような仕組みをサポートしている模様って事で

Google Cloud Endpoints(Java)を使ってみた ng-infinite-scroll