I have a directive with isolated scope with a value with two way binding to the parent scope. I am calling a method that changes the value in the parent scope, but the chang
Instead of using $scope.$apply()
, try using $scope.$applyAsync();
The answer Use $scope.$apply() is completely incorrect.
The only way that I have seen to update the scope in your directive is like this:
angular.module('app')
.directive('navbar', function () {
return {
templateUrl: '../../views/navbar.html',
replace: 'true',
restrict: 'E',
scope: {
email: '='
},
link: function (scope, elem, attrs) {
scope.$on('userLoggedIn', function (event, args) {
scope.email = args.email;
});
scope.$on('userLoggedOut', function (event) {
scope.email = false;
console.log(newValue);
});
}
}
});
and emitting your events in the controller like this:
$rootScope.$broadcast('userLoggedIn', user);
This feels like such a hack I hope the angular gurus can see this post and provide a better answer, but as it is the accepted answer does not even work and just gives the error $digest already in progress
One thing most people forget is that you can't just declare an isolated scope with the object notation and expect parent scope properties to be bound. These bindings only work if attributes have been declared through which the binding 'magic' works. See for more information:
https://umur.io/angularjs-directives-using-isolated-scope-with-attributes/
Use $scope.$apply()
after changing the $scope.myValue
in your controller like:
testApp.controller('testCtrl', function ($scope) {
$scope.myValue = '1';
$scope.update = function () {
// Expecting local variable k, or $scope.pkey to have been
// updated by calls in the directive's scope.
console.log('CTRL:', $scope.myValue);
$scope.myValue = "2";
$scope.$apply();
console.log('CTRL:', $scope.myValue);
};
});
Using $apply() like the accepted answer can cause all sorts of bugs and potential performance hits as well. Settings up broadcasts and whatnot is a lot of work for this. I found the simple workaround just to use the standard timeout to trigger the event in the next cycle (which will be immediately because of the timeout). Surround the parentUpdate() call like so:
$timeout(function() {
$scope.parentUpdate();
});
Works perfectly for me. (note: 0ms is the default timeout time when not specified)