41

So I basically want to be able to trigger an event and then have a directive compile and insert its self to a position in the DOM. Currently I have something like this

//controller
  angular.module('app').controller('MainCtrl', function ($scope, $compile) {

    $scope.$on('insertItem',function(ev,attrs){
      var el = $compile( "<chart></chart>" )( $scope );
      $scope.insertHere = el;
    });

  });


// directive
 angular.module('app')
  .directive('chart', function () {
    return {
      template: '<div>My chart</div>',
      restrict: 'E',
      link: function postLink(scope, element, attrs) {
        element.text('this is a chart');
      }
    };
  });

I am able to see the object "el" with all that I need but I'm not able to insert it into the DOM... any clues?

nshew13
  • 3,052
  • 5
  • 25
  • 39
climboid
  • 6,932
  • 14
  • 44
  • 71
  • Possible duplicate of [Dynamically add directive in AngularJS](http://stackoverflow.com/questions/15279244/dynamically-add-directive-in-angularjs) – Castro Roy Jul 29 '16 at 20:38

1 Answers1

48

You have to create the dom element first, then compile it and add it to the document. Something like this:

$scope.$on('insertItem',function(ev,attrs){
  var chart = angular.element(document.createElement('chart'));
  var el = $compile( chart )( $scope );

  //where do you want to place the new element?
  angular.element(document.body).append(chart);

  $scope.insertHere = el;
};

I've created a simple example here: http://plnkr.co/edit/n7SZpyeQ9nbjVSYA7ibB?p=preview

joakimbl
  • 18,081
  • 5
  • 54
  • 53
  • 4
    How would I access `$compile` if I were creating the element outside of Angular? – Hengjie Oct 23 '13 at 10:45
  • Hi, would you please provide ideas on my new proposed API to make programmatically adding directives a simpler process? https://github.com/angular/angular.js/issues/6950 Thanks! – trusktr Apr 05 '14 at 04:25
  • 1
    @Hengjie It needs to compile the element with reference to a particular scope (inside angular). There are no directives outside of angular. Directives are tied to scopes within your app. Alternately you can use the jQLite inside angular and do event handlers that way (`angular.element('body')`). – Kevin Beal Jun 03 '14 at 21:36
  • 1
    is this a normal practice, or considered against the angular grain? – FlavorScape Jun 12 '14 at 22:15
  • 1
    It definitely feels it's against the Angular ways, though the alternative isn't any more prettier. I basically lazily triggered `ng-include` depending on an event and let `ng-include` handle the compilation and linking for me. If anyone is interested, I can dig up the code and add it as an answer. – Hengjie Jun 14 '14 at 06:54
  • hengije please do so. That would be very helpful. – schlingel Feb 10 '15 at 14:09
  • It is not necessary to determine the dependencies of the directive you're creating, nor inject them. [Example here introduces a dependency on a factory `'f'`, but I continue to use @joakimbl's code which simply compiles like this ` $compile( chart )( $scope );`](http://plnkr.co/edit/80ALlJ6SwKgaLl0kIcr0?p=preview) – Nate Anderson Nov 08 '16 at 04:27
  • It would be nice to update the answer with case the directive has any attributes, which need to be provided. – Vojtech Ruzicka Nov 18 '16 at 14:21
  • Does anyone have an example of $scope.insertHere? I try referencing a variable like that and just get something along the lines of `{context:"0"}`. I dont have the exact code in front of me. – Bryant Makes Programs May 26 '17 at 14:30