AngularJS1.5でコンポーネントの中にコンポーネントを配置した場合の、その親子間でやりとりする方法を調べた。

デモ:http://plnkr.co/edit/6OtbJKlX121gkwEVJJsj?p=preview

親から子に値を渡す

バインディングで引き渡す:

// Parent component
angular.module(MY_MODULE)
  .component('myParent', {
    controllerAs: 'parent',
    controller: function() {
      this.names = ['foo', 'bar', 'baz']
    },
    template: (
      '<h1>Parent</h1>' + 
      '<my-child names="parent.names"></my-child>'
      ),
  })

// Child component
angular.module(MY_MODULE)
  .component('myChild', {
    bindings: {
      names: '=',
    },
    controllerAs: 'child',
    template: (
      '<button ng-repeat="name in child.names" ng-bind="name"></button>'
      ),
  })
  • 親コンポーネントから子コンポーネントにアトリビュートとして、names="parent.names"などとバインディングでデータを渡す
  • 子コンポーネントでbindings: {names: '='}としてコントローラにバインドする
  • あとはコントローラのプロパティとして使えるので、なんなりと好きなように、ng-repeatで回したり

子から親に通知

子コンポーネント側でなにか起きた時に、親側で処理させるために親コンポーネントに通知したい

// Parent component
angular.module(MY_MODULE)
  .component('myParent', {
    controllerAs: 'parent',
    controller: function() {
      this.names = ['foo', 'bar', 'baz']
      this.message = ''

      this.onClickButton = function(name) {
        this.message = 'From child: ' + name
      }
    },
    template: (
      '<h1>Parent</h1>' + 
      '<my-child names="parent.names"' +
      '          on-child-fired="parent.onClickButton($name)"></my-child>' +
      '<div ng-bind="parent.message"></div>'
      ),
  })

// Child component
angular.module(MY_MODULE)
  .component('myChild', {
    bindings: {
      names: '=',
      onChildFired: '&',
    },
    controllerAs: 'child',
    controller: function() {
      this.onClicked = function(name) {
        this.onChildFired({'$name': name})
      }
    },
    template: (
      '<button ng-repeat="name in child.names" ng-bind="name"' +
      '        ng-click="child.onClicked(name)"></button>'
      ),
  })
  • 子コンポーネント側で、bindings: {onChildFired: '&'}などとして、ハンドラを受け取れるようにする
  • 子コンポーネント側から親に通知する場合、子のコントローラ内でthis.onChildFired(...)として、関数を呼び出してやる
    • 引数はオブジェクトで{'$name': name}などとして、ハンドラ内で参照する名前:値で渡す
  • 親コンポーネントからはon-child-fired="parent.onClickButton($name)"などと受け取って処理する

親から子に通知

親から値をバインディングとして子に渡すだけならいいが、なにか変更があったときに処理を呼び出したい、といった場合に簡単なやり方がわからなかった…。

AngularJS: Developer Guide: Componentsの「Intercomponent Communication」のように、子コンポーネント側でrequire: '^parent'として$onInitで親に自分を受け渡しておく、ということになるんだろうか。

(Angular2では親コンポーネントから@ViewChildとか@ContentChildとかで子コンポーネントを取れるので、簡単に呼び出せる)