aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatias Niemelä2013-08-13 20:51:03 -0400
committerMisko Hevery2013-09-03 17:06:49 -0700
commit4e15c4fb47e93c1f6619a09125bc9a350e39b113 (patch)
tree6de258934679cf4a35583335b841db263b7c0f5f
parent4382df03fa1962aed027742c1b463406c40653c9 (diff)
downloadangular.js-4e15c4fb47e93c1f6619a09125bc9a350e39b113.tar.bz2
chore($rootScope): provide support to execute a function after the digest cycle is complete
-rw-r--r--src/ng/rootScope.js16
-rw-r--r--test/ng/rootScopeSpec.js74
2 files changed, 90 insertions, 0 deletions
diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js
index 18c54434..d3b2762d 100644
--- a/src/ng/rootScope.js
+++ b/src/ng/rootScope.js
@@ -119,6 +119,7 @@ function $RootScopeProvider(){
this['this'] = this.$root = this;
this.$$destroyed = false;
this.$$asyncQueue = [];
+ this.$$postDigestQueue = [];
this.$$listeners = {};
this.$$isolateBindings = {};
}
@@ -133,6 +134,7 @@ function $RootScopeProvider(){
Scope.prototype = {
+ constructor: Scope,
/**
* @ngdoc function
* @name ng.$rootScope.Scope#$new
@@ -167,6 +169,7 @@ function $RootScopeProvider(){
child.$root = this.$root;
// ensure that there is just one async queue per $rootScope and it's children
child.$$asyncQueue = this.$$asyncQueue;
+ child.$$postDigestQueue = this.$$postDigestQueue;
} else {
Child = function() {}; // should be anonymous; This is so that when the minifier munges
// the name it does not become random set of chars. These will then show up as class
@@ -494,6 +497,7 @@ function $RootScopeProvider(){
var watch, value, last,
watchers,
asyncQueue = this.$$asyncQueue,
+ postDigestQueue = this.$$postDigestQueue,
length,
dirty, ttl = TTL,
next, current, target = this,
@@ -566,6 +570,14 @@ function $RootScopeProvider(){
} while (dirty || asyncQueue.length);
clearPhase();
+
+ while(postDigestQueue.length) {
+ try {
+ postDigestQueue.shift()();
+ } catch (e) {
+ $exceptionHandler(e);
+ }
+ }
},
@@ -696,6 +708,10 @@ function $RootScopeProvider(){
this.$$asyncQueue.push(expr);
},
+ $$postDigest : function(expr) {
+ this.$$postDigestQueue.push(expr);
+ },
+
/**
* @ngdoc function
* @name ng.$rootScope.Scope#$apply
diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js
index d6a684a7..656385e9 100644
--- a/test/ng/rootScopeSpec.js
+++ b/test/ng/rootScopeSpec.js
@@ -12,6 +12,12 @@ describe('Scope', function() {
}));
+ it('should expose the constructor', inject(function($rootScope) {
+ if (msie) return;
+ expect($rootScope.__proto__).toBe($rootScope.constructor.prototype);
+ }));
+
+
it('should not have $root on children, but should inherit', inject(function($rootScope) {
var child = $rootScope.$new();
expect(child.$root).toEqual($rootScope);
@@ -672,6 +678,74 @@ describe('Scope', function() {
expect(log).toEqual('parent.async;child.async;parent.$digest;child.$digest;');
}));
+ it('should not run another digest for an $$postDigest call', inject(function($rootScope) {
+ var internalWatchCount = 0;
+ var externalWatchCount = 0;
+
+ $rootScope.internalCount = 0;
+ $rootScope.externalCount = 0;
+
+ $rootScope.$evalAsync(function(scope) {
+ $rootScope.internalCount++;
+ });
+
+ $rootScope.$$postDigest(function(scope) {
+ $rootScope.externalCount++;
+ });
+
+ $rootScope.$watch('internalCount', function(value) {
+ internalWatchCount = value;
+ });
+ $rootScope.$watch('externalCount', function(value) {
+ externalWatchCount = value;
+ });
+
+ $rootScope.$digest();
+
+ expect(internalWatchCount).toEqual(1);
+ expect(externalWatchCount).toEqual(0);
+ }));
+
+ it('should run a $$postDigest call on all child scopes when a parent scope is digested', inject(function($rootScope) {
+ var parent = $rootScope.$new(),
+ child = parent.$new(),
+ count = 0;
+
+ $rootScope.$$postDigest(function() {
+ count++;
+ });
+
+ parent.$$postDigest(function() {
+ count++;
+ });
+
+ child.$$postDigest(function() {
+ count++;
+ });
+
+ expect(count).toBe(0);
+ $rootScope.$digest();
+ expect(count).toBe(3);
+ }));
+
+ it('should run a $$postDigest call even if the child scope is isolated', inject(function($rootScope) {
+ var parent = $rootScope.$new(),
+ child = parent.$new(true),
+ signature = '';
+
+ parent.$$postDigest(function() {
+ signature += 'A';
+ });
+
+ child.$$postDigest(function() {
+ signature += 'B';
+ });
+
+ expect(signature).toBe('');
+ $rootScope.$digest();
+ expect(signature).toBe('AB');
+ }));
+
it('should cause a $digest rerun', inject(function($rootScope) {
$rootScope.log = '';
$rootScope.value = 0;