AngularJS1.5で親子コンポーネント間のやりとり

2016-04-14

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とかで子コンポーネントを取れるので、簡単に呼び出せる)