親Scopeの値は参照できるけど代入はうまくいかないよ父さん
angularの$scopeの親子関係はたぶんprototype chainで作ってるだけだから親scopeの値に代入したつもりでも子scopeの値が新しく出来るだけでうまく動かない。
— Hiroyuki Anai (@pirosikick) 2013, 11月 26
Scope.$newのところを読んだけどやっぱりそうだった。
Child = function() {}; // should be anonymous; This is so that when the minifier munges // the name it does not become random set of chars. This will then show up as class // name in the debugger. Child.prototype = this; child = new Child(); child.$id = nextUid(); // 省略 return child;
なので、親scopeに定義してある変数に対して子scopeから値を代入したつもりでも、実際には子scopeに値を定義してしまっていて、次からはそっちを見るようになるのでうまくいかない。
例えば、↓では、visibleChildを使って子要素の表示・非表示を制御しているが、一度「Hide This」を押してしまうと、「Show Child」を押しても反応しない。
<body ng-app> <div class="parent" ng-controller="ParentCtrl" ng-init="visibleChild = true"> <a ng-click="visibleChild = true">Show Child</a> <div class="child" ng-controller="ChildCtrl" ng-show="visibleChild"> <h2>Child</h2> <a ng-click="visibleChild = false">Hide This</a> </div> </div> </body>
親Scopeにsetterを用意する
直接代入することを避け、確実に親Scopeに値が入るようにする。
function ParentCtrl ($scope) { $scope.visibleChild = true; // visibleChildのsetter $scope.setVisibleChild = function (flag) { $scope.visibleChild = !!flag; } }
<body ng-app> <div class="parent" ng-controller="ParentCtrl"> <a ng-click="setVisibleChild(true)">Show Child</a> <div class="child" ng-controller="ChildCtrl" ng-show="visibleChild"> <h2>Child</h2> <a ng-click="setVisibleChild(false)">Hide This</a> </div> </div> </body>
本当はchildをdirective化してdirecvtive内にフラグを持ってうまいことやるのがいいのかもしれないが。directiveをもうちょい勉強して出直します。 もしくは$boardcastや$emitを使ってeventで操作するのがいいのか、誰かいい方法を知っていたら教えて下さいませ。