Skip to content

Commit

Permalink
feat($compile): allow directives to modify interpolated attributes
Browse files Browse the repository at this point in the history
A directive can now set/update/remove attribute values even those containing
interpolation during the compile phase and have the new value be picked up
during the compilation.

For example in template:

<div replace-directive some-attr-or-directive="{{originalInterpolationValue}}"></div>

the replace-directive can now replace the value of some-attr-or-directive during compilation
which produces this intermitent template:

<div replace-directive some-attr-or-directive="{{replacedInterpolationValue}}"></div>

or even

<div replace-directive some-attr-or-directive="replacedStaticValue"></div>

as well as

<div replace-directive some-attr-or-directive></div>
  • Loading branch information
tleruitte authored and IgorMinar committed Mar 1, 2013
1 parent eb53423 commit fe8d893
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
14 changes: 8 additions & 6 deletions src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -1102,11 +1102,13 @@ function $CompileProvider($provide) {
compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) {
var $$observers = (attr.$$observers || (attr.$$observers = {}));

if (name === 'class') {
// we need to interpolate classes again, in the case the element was replaced
// and therefore the two class attrs got merged - we want to interpolate the result
interpolateFn = $interpolate(attr[name], true);
}
// 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);

// if attribute was updated so that there is no interpolation going on we don't want to
// register any observers
if (!interpolateFn) return;

attr[name] = interpolateFn(scope);
($$observers[name] || ($$observers[name] = [])).$$inter = true;
Expand Down Expand Up @@ -1203,7 +1205,7 @@ function directiveNormalize(name) {
* @param {string} name Normalized element attribute name of the property to modify. The name is
* revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
* property to the original name.
* @param {string} value Value to set the attribute to.
* @param {string} value Value to set the attribute to. The value can be an interpolated string.
*/


Expand Down
14 changes: 14 additions & 0 deletions test/ng/compileSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,12 @@ describe('$compile', function() {
expect(attr.$observe('someAttr', observeSpy)).toBe(observeSpy);
};
});
directive('replaceSomeAttr', valueFn({
compile: function(element, attr) {
attr.$set('someAttr', 'bar-{{1+1}}');
expect(element).toBe(attr.$$element);
}
}));
}));


Expand Down Expand Up @@ -1544,6 +1550,14 @@ describe('$compile', function() {
}));


it('should allow directive to replace interpolated attributes before attr interpolation compilation', inject(
function($compile, $rootScope) {
element = $compile('<div some-attr="foo-{{1+1}}" replace-some-attr></div>')($rootScope);
$rootScope.$digest();
expect(element.attr('some-attr')).toEqual('bar-2');
}));


it('should call observer of non-interpolated attr through $evalAsync',
inject(function($rootScope, $compile) {
$compile('<div some-attr="nonBound" observer></div>')($rootScope);
Expand Down

0 comments on commit fe8d893

Please sign in to comment.