AngularJS Directives: Change $scope not reflected in UI
JavascriptAngularjsJavascript Problem Overview
I'm trying to making some custom elements with AngularJS's and bind some events to it, then I notice $scope.var won't update UI when used in a binding function.
Here is a simplified example that describing the probelm:
HTML:
<!doctype html>
<html ng-app="test">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="Ctrl2">
<span>{{result}}</span>
<br />
<button ng-click="a()">A</button>
<button my-button>B</button>
</div>
</body>
</html>
JS:
function Ctrl2($scope) {
$scope.result = 'Click Button to change this string';
$scope.a = function (e) {
$scope.result = 'A';
}
$scope.b = function (e) {
$scope.result = 'B';
}
}
var mod = angular.module('test', []);
mod.directive('myButton', function () {
return function (scope, element, attrs) {
//change scope.result from here works
//But not in bind functions
//scope.result = 'B';
element.bind('click', scope.b);
}
});
DEMO : http://plnkr.co/edit/g3S56xez6Q90mjbFogkL?p=preview
Basicly, I bind click
event to my-button
and want to change $scope.result
when user clicked button B (similar to ng-click:a()
on button A). But the view won't update to the new $scope.result
if I do this way.
What did I do wrong? Thanks.
Javascript Solutions
Solution 1 - Javascript
Event handlers are called "outside" Angular, so although your $scope
properties will be updated, the view will not update because Angular doesn't know about these changes.
Call $scope.$apply()
at the bottom of your event handler. This will cause a digest cycle to run, and Angular will notice the changes you made to the $scope
(because of the $watches
that Angular set up due to using {{ ... }}
in your HTML) and update the view.
Solution 2 - Javascript
This might be also a result of different problem but with the same symptoms.
If you destroy a parent scope of the one that is assigned to the view, its changes will not affect the view in any way even after $apply()
call. See the example - you can change the view value through the text input, but when you click Destroy parent scope!, model is not updated anymore.
I do not consider this as a bug. It is rather result of too hacky code in application :-)
I faced this problem when using Angular Bootstrap's modal. I tried to open second modal with scope of the first one. Then, I immediately closed the first modal which caused the parent scope to be destroyed.
Solution 3 - Javascript
use timeout
$timeout(function () { code.... }, 0);