1

If I register an element-oriented directive with AngularJS ahead of time, can I then simply directly inject into the DOM (e.g. via document.appendChild) a node matching the directive element (e.g. <my-directive-name my-attribute='foo'></my-directive-name>, and AngularJS will render said directive in its place (perhaps needing a manual digest trigger)?

my-directive-template.html

  <div>
    hello world
  </div>

my-directive-name.js

function MyDirectiveName() {
        return {
            scope: {
              'myAttribute': '&',
            },
            template: template,
            replace: true,
            controller: controller,
            restrict: 'E',
            // ...
        };
}

Angular configuration:

//...
angular.directive('my-directive-name', require('my-directive-name'))
//...

Start DOM:

<body></body>

Then I dynamically append a child node:

<body>
   <my-directive-name my-attribute='foo'>
   </my-directive-name> 
</body>

Then I do something to make Angular realize that something has changed (what is this?):

End DOM:

<body>
   <div>
     hello world
   </div> 
</body>
7
  • Could you post simple example and the required result? I think this should be very easy by using ng-if but I might don't quite get what you intend to do. Commented Jul 28, 2015 at 17:28
  • possible duplicate of Adding a new element into the DOM with angularjs does not initiate it Commented Jul 28, 2015 at 17:38
  • this doesn't feel angular at all. I comment on at least one post every day about angular saying the same thing. It is counter to the purpose of angular to manipulate the DOM except in extreme edge cases. In angular, you should code against your data, not the DOM. Commented Jul 28, 2015 at 17:41
  • @Claies Please indicate how I can render into the DOM AngularJS directives when the directives to be rendered are not known ahead of time that meets your requirement for "feeling Angular". Commented Jul 28, 2015 at 17:46
  • I'm not even sure I understand what you are asking in your comment, but I've used templates and combinations of ng-if, ng-show, ng-repeat, etc. to render content based on data types in plenty of projects. I can't give you a solution to a hypothetical "I don't know what it is ahead of time" type question; why wouldn't you know ahead of time, somewhere in the flow of the app? you aren't letting the users pick the HTML they want rendered on the page, after all.... Commented Jul 28, 2015 at 17:53

2 Answers 2

1

You would need to be sure to $compile the element first before just appending it to the DOM. Here is a trivial example showing how you can use the $compile function outside of angular code (through setTimeout) to add to the DOM.

(function(angular) {

  angular.module('myApp', [])
    .directive('myDirectiveName', MyDirectiveName);

  function MyDirectiveName() {
    return {
      restrict: 'E',
      template: '<div>Custom Directive with {{myAttr}} as my-attribute</div>',
      scope: {
        myAttr: '@myAttribute'
      }
    };
  }

  // run this later.
  setTimeout(function() {

    var appDiv = angular.element(document.getElementById('app'));
    // Get the injector to compile
    var $injector = appDiv.injector();
    var $compile = $injector.get('$compile');
    // compile new elems
    var barLink = $compile(angular.element('<my-directive-name my-attribute="bar"></my-directive-name>'));
    var bazLink = $compile(angular.element('<my-directive-name my-attribute="baz"></my-directive-name>'));

    // append both elements by linking against scope
    appDiv.append(barLink(appDiv.scope()));
    appDiv.append(bazLink(appDiv.scope()));
  }, 3000);
}(angular));
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" id="app">
  <my-directive-name my-attribute="foo"></my-directive-name>
</div>

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

Comments

1

You need to $compile the element before you append it. Here's a Fiddle: http://jsfiddle.net/ftfish/KyEr3/

Duplicate question: Adding a new element into the DOM with angularjs does not initiate it

Comments

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.