AngularJS: How to compile a custom directive added by a service?

Using AngularJS and UI Bootstrap, I want to dynamically add Alerts to the DOM. But if I dynamically add an <alert> element to the DOM, it is not automatically compiled. I tried to use $ compilation, but it doesn't seem to understand tag names that are not present in AngularJS core. How can I achieve this? Is this even the correct way to "manually" add elements to the DOM in services?

See Plunker . The warning in #hardcodedalert compiled and displayed correctly, but the content of #dynamicalert does not compile.

Edit:

Later on, I want the alerts to appear in different contexts and locations on my web page and that's why I created a constructor function for alerts to have a new instance in each controller that needs alerts. And just out of curiosity, I was wondering if it is possible to add <alert> tags dynamically instead of including them in the html.

+3


source to share


1 answer


I've updated your plunker to do what "angular" you are trying to do.

There are several problems with what you were trying to do. The biggest of which was DOM manipulation within your controller. I can see that you tried to compensate for this by handling some of this in the service, but you were still referencing the DOM in your controller when you used JQuery to select that element.

In general, your directives didn't compile because you are still developing in the JQuery style. Typically, you should let the directives handle the addition and removal of DOM elements for you. This handles all instructions for compilation and processing. If you add things manually as you tried, you will have to use the $ compilation provider to compile and run against the scope ... that would be a testing and maintenance nightmare as well.

One more note: I'm not sure if you want a service that returned an object with a constructor, so I made it just an object. It should be noted that services are created and managed in one go, so every instance of this $ alertService that you pass to any controller will be the same. This is an interesting way to exchange data, although it is recommended to use $ rootScope in most cases.

Here is the code:



app.factory('alertservice', [function() {
  function Alert() {
    this.alerts = [];
    this.addAlert = function(alert) {
      this.alerts.push(alert);
    };
  }
  return {
    Alert: Alert
  };
}]);

app.controller('MainCtrl', function($scope, alertservice) {
  var myAlert = new alertservice.Alert();
  $scope.alerts = myAlert.alerts;
  $scope.add = function() {
    myAlert.addAlert({"text": "bar"});
  };
});

      

Here are the important parts of the updated markup:

  <body ng-controller="MainCtrl">
    <div id="dynamicalert">
      <alert ng-repeat="alert in alerts">{{alert.text}}</alert>
    </div>
    <button ng-click="add()">Add more alerts...</button>
  </body>

      

EDIT: Updated to reflect your request

+4


source







All Articles