4

For example, UI Bootstrap has a directive called 'typeahead' that suggests values for a field. Let's say I want to make a directive that I can use as an attribute for an element that will cause colours to be suggested for that element.

Here's an attempt that fails...

Directive:

angular.module('myApp')
  .directive('suggestcolors', function () {
    return {
      compile: function compile(element, attrs) {
        attrs.$set("typeahead", "color for color in ['red', 'blue', 'green']");
      }
    };
  });

View:

<textarea ng-model="foo" suggestcolors></textarea>

When I inspect the textarea, the attribute has been set, but it doesn't do anything. The same thing happens if I move the change to attrs to the link function. Setting the typeahead attribute directly in the view works as expected:

<textarea ng-model="foo" typeahead="color for color in ['red', 'blue', 'green']"></textarea>

(But I want to be able to insert this attribute dynamically, for reasons of DRY. My actual use case is more complicated than this.)

A similar question was asked here (about dynamically adding ng-click behaviour in the compile step), but never directly answered.

1 Answer 1

6

After the compilation, AngularJS only calls $compile for all of the child elements. The element itself is not automatically recompiled, so adding a directive at this stage will not have effect. In your case, I think you can change it from a compile function to a link function (so you get a scope argument), and call $compile(element)(scope) yourself.

See this Fiddle where I have a directive that adds style="color: red", and another directive that "dynamically" adds that directive. It doesn't work, unless I call $compile afterwards.

HTH!

Sign up to request clarification or add additional context in comments.

4 Comments

If you take a look at the console in that Fiddle, you'll see that an infinite recursion happens (RangeError: Maximum call stack size exceeded). Also, calling $compile like this is a way for watchers to leak as you don't unregister the watchers called by the previous call to $compile.
An example of leaking watchers: plnkr.co/edit/3Y1BoNuNO2HFA98JS7oR?p=preview
That's a good point, I didn't spot that! I meant to unset the attribute after compiling, but your point of leaking watches makes sense. If you have a complete answer to the question, I'll upvote your answer. Thanks!
As for the question in the title, no, I don't have any really good answer to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.