Help us understand the problem. What is going on with this article?

[AngularJS] 複数Contoller間で、Service,$rootScope,$emitを利用して変数を共有した時のメモ

More than 5 years have passed since last update.

angularは変数の共有がなかなか慣れるまで面倒くさい。
詰まったポイントをメモします。

要件

  • 異なるコントローラー間で変数を受け渡したい
    • そのために変数共有用のgetter/setterを実装したserviceを作成
    • serviceを通して変数を共有する

NGだったパターン

ファイルは4つ。

  • haml:template.html.haml
  • coffeescript:shared_number.js.coffee
  • coffee:parent_controller.js.coffee
  • coffee:child_controller.js.coffee
template.html.haml
-# SET-NUMBERをクリックすると、直下のdivのchild_numに番号が表示されることを期待
%div( ng-controller='ParentController')
  %a( ng-click='set_child_num(69)' ) SET-NUMBER!
  %div( ng-controller='ChildController')
    {{child_num}}


shared_number.js.coffee
App.factory 'SharedNumberFactory', ['$rootScope', ($rootScope) ->
  number = ''

  return{
    number:{
      get: ()->
        return parseInt(number)
      set: (i)->
        number = i
        $rootScope.$broadcast('event:onSetNumber')
    }
  }
] 
parent_controller.js.coffee
App.controller "ParentController", ($scope, SharedNumberFactory) ->
  $scope.set_child_num = (num) ->
    SharedNumberFactory.number.set(num)
child_controller.js.coffee
App.controller "ChildController", ($scope, SharedNumberFactory) ->
  $scope.$on('event:onSetNumber', () ->
    $scope.child_num = SharedNumberFactory.number.get()
    console.log 'set child_num'

と記述した。

イメージしたプロセスは以下のとおり

  • 1.ParentControllerのset_child_num をng-clickで実行。
    • SharedNumberFactory内のset(num)で、SharedNumberFactoryに番号をセット。
  • 2.SharedNumberFactoryで番号をsetし、'event:onSetNumber'リスナーを登録しているオブジェクトに波及させる
  • 3.ChildControllerには'event:onSetNumber'が登録されているので、その内部が実行され、child_numに数字が登録される

だが、

2.SharedNumberFactoryで番号をsetし、'event:onSetNumber'リスナーを登録しているオブジェクトに波及させる
が実行されない。

どうやらリスナーとして、ChildControllerに'event:onSetNumber'が登録されていない模様。

Factoryの$broadcastを実行する前に、
どういうわけか、
lisnerとして'event:onSetNumber'が登録されていないのが原因の模様。

たとえば、Factoryやserviceを使わずとも
親controllerに$broadcastを実行し、子controllerで$onを登録しているだけのパターンでも
その減少が起こりうる場合があるとのこと。

OKパターン

(参考) [AngularJS]コントローラ間のイベント通知では$broadcastが使えない場合がある
http://d.hatena.ne.jp/Kazzz/20140809/p1

上記アドレスを参考に下記のようなコードに書き換えた。
書き換えたファイルは
- coffee:shared_number.js.coffee
- coffee:child_controller.js.coffee
の2つ

shared_number.js.coffee
App.factory 'SharedNumberFactory', ['$rootScope', ($rootScope) ->
  number = ''

  return{
    number:{
      get: ()->
        return parseInt(number)
      set: (i)->
        number = i
        $rootScope.$on 'event:onControllerLoaded', () -> 
          $rootScope.$broadcast('event:onSetNumber') //★追加
    }
  }
] 
child_controller.js.coffee
App.controller "ChildController", ($scope, SharedNumberFactory) ->
  $scope.$on('event:onSetNumber', () ->
    $scope.child_num = SharedNumberFactory.number.get()
    console.log 'set child_num'
  $scope.$emit('event:onControllerLoaded', this) //★追加

大きな変更は2つ。
ChildControllerが読み出されたタイミングで$emit()を利用して、
- $scopeに登録されているリスナー'event:onControllerLoaded'に自身の存在を告知。
- その中に$broadcast()メソッドを登録する

これでFactory/Serviceや親コントローラに自身の存在を登録させる事ができる。

参考

[AngularJS]コントローラ間のイベント通知では$broadcastが使えない場合がある
http://d.hatena.ne.jp/Kazzz/20140809/p1

Angular JS で複数のコントローラ間でモデル(状態や値)を共有する方法 3 種類
http://qiita.com/sunny4381/items/aeae1e154346b5cf6009

hanzochang
Director 兼 雑用
http://lab.heathrow.co.jp
neuro
二次交通に特化したモビリティプラットフォームRYDEの企画運営する東京のスタートアップです。
https://ryde-inc.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした