diff --git a/src/ng/compile.js b/src/ng/compile.js index f0b7ba9e5952..84432647fe01 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1717,33 +1717,37 @@ function $CompileProvider($provide) { } directives.push({ - priority: -100, - compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) { - var $$observers = (attr.$$observers || (attr.$$observers = {})); - - if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { - throw $compileMinErr('nodomevents', - "Interpolations for HTML DOM event attributes are disallowed. Please use the " + - "ng- versions (such as ng-click instead of onclick) instead."); - } + priority: 100, + compile: function() { + return { + pre: function attrInterpolatePreLinkFn(scope, element, attr) { + var $$observers = (attr.$$observers || (attr.$$observers = {})); + + if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { + throw $compileMinErr('nodomevents', + "Interpolations for HTML DOM event attributes are disallowed. Please use the " + + "ng- versions (such as ng-click instead of onclick) instead."); + } - // we need to interpolate again, in case the attribute value has been updated - // (e.g. by another directive's compile function) - interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name)); - - // if attribute was updated so that there is no interpolation going on we don't want to - // register any observers - if (!interpolateFn) return; - - // TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the - // actual attr value - attr[name] = interpolateFn(scope); - ($$observers[name] || ($$observers[name] = [])).$$inter = true; - (attr.$$observers && attr.$$observers[name].$$scope || scope). - $watch(interpolateFn, function interpolateFnWatchAction(value) { - attr.$set(name, value); - }); - }) + // we need to interpolate again, in case the attribute value has been updated + // (e.g. by another directive's compile function) + interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name)); + + // if attribute was updated so that there is no interpolation going on we don't want to + // register any observers + if (!interpolateFn) return; + + // TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the + // actual attr value + attr[name] = interpolateFn(scope); + ($$observers[name] || ($$observers[name] = [])).$$inter = true; + (attr.$$observers && attr.$$observers[name].$$scope || scope). + $watch(interpolateFn, function interpolateFnWatchAction(value) { + attr.$set(name, value); + }); + } + }; + } }); } diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 0bba6b3737ab..72165b7ee67c 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -1591,7 +1591,7 @@ describe('$compile', function() { ); - it('should process attribute interpolation at the beginning of the post-linking phase', function() { + it('should process attribute interpolation in pre-linking phase at priority 100', function() { module(function() { directive('attrLog', function(log) { return { @@ -1600,22 +1600,36 @@ describe('$compile', function() { return { pre: function($scope, $element, $attrs) { - log('preLink=' + $attrs.myName); + log('preLinkP0=' + $attrs.myName); }, - post: function($scope, $element) { + post: function($scope, $element, $attrs) { log('postLink=' + $attrs.myName); } } } } - }) + }); + }); + module(function() { + directive('attrLogHighPriority', function(log) { + return { + priority: 101, + compile: function() { + return { + pre: function($scope, $element, $attrs) { + log('preLinkP101=' + $attrs.myName); + } + }; + } + } + }); }); inject(function($rootScope, $compile, log) { - element = $compile('
')($rootScope); + element = $compile('
')($rootScope); $rootScope.name = 'angular'; $rootScope.$apply(); log('digest=' + element.attr('my-name')); - expect(log).toEqual('compile={{name}}; preLink={{name}}; postLink=; digest=angular'); + expect(log).toEqual('compile={{name}}; preLinkP101={{name}}; preLinkP0=; postLink=; digest=angular'); }); }); @@ -1758,6 +1772,32 @@ describe('$compile', function() { expect(element.text()).toBe('AHOJ|ahoj|AHOJ'); }); }); + + + it('should make attributes observable for terminal directives', function() { + module(function() { + directive('myAttr', function(log) { + return { + terminal: true, + link: function(scope, element, attrs) { + attrs.$observe('myAttr', function(val) { + log(val); + }); + } + } + }); + }); + + inject(function($compile, $rootScope, log) { + element = $compile('
')($rootScope); + expect(log).toEqual([]); + + $rootScope.myVal = 'carrot'; + $rootScope.$digest(); + + expect(log).toEqual(['carrot']); + }); + }) });