简体   繁体   中英

how to pass data from service to directive in angular.js

I have an alert service which shows alerts on top of the page. I have written a service and a directive which feeds off of the data coming from the service.

However, when i add a service using teh alert service and pass it to the directive, it does not show up, the alert

here is my code

The template

<div class="alert alert-{{alert.type}}">
    <button type="button" class="close" data-dismiss="alert" aria-hidden="true" ng-click="close()">&times;</button>
    <div ng-bind="::alert.message" ></div>
</div>

Alert Service and directive

angular.module('test')
    .service('alertService', function() {
        var alerts = [];
        this.add = function(type, msg) {
            var self = this;
            var alert = {
                type: type,
                msg: msg,
                close: function() {
                    return self.closeAlert(alert);
                }
            };
            return alerts.push(alert);
        };
        this.closeAlert = function(alert) {
            return this.closeAlertIdx(alerts.indexOf(alert));
        };
        this.closeAlertIdx = function(index) {
            return alerts.splice(index, 1);
        };
        this.clear = function() {
            alerts = [];
        };
        this.getAlerts = function() {
            return alerts;
        };
    })
    .directive('alertList', ['alertService', function(alertService) {
        return {
            restrict: 'EA',
            templateUrl: 'templates/alert/alert.html',
            replace: true,
            link: function(scope) {
                scope.alerts = alertService.getAlerts();
            }
        };
    }]);

In the index.html , i have referenced the alert-list directive

<div>
   <alert-list ng-repeat="alert in alerts">
   </alert-list>
</div>

In my controller i have,

alertService.add('info', 'This is a message');

I see that the alertService adds the alert to the array, but when i put a breakpoint in the link function of the directive, it never gets called

services are function that return an object, so you had to modify your service to be more or less like this:

.service('alertService', function() {
  var alerts = [];
  return{
      add : function(type, msg) {
          var self = this;
          var alert = {
              type: type,
              msg: msg,
              close: function() {
                  return self.closeAlert(alert);
              }
          };
          return alerts.push(alert);
      },
      closeAlert: function(alert) {
         return this.closeAlertIdx(alerts.indexOf(alert));
      },
      closeAlertIdx : function(index) {
         return alerts.splice(index, 1);
      },
      clear: function() {
           alerts = [];
      },
      getAlerts: function() {
          return alerts;
      }
 })

The link function is only called once, when the directive element is created. When your app starts up, the link function will be called, and the scope.alerts will be set to an empty list.

I think you need to move the ng-repeat to the outer div of the alert template, rather than on the alert-list element.

Since the link function is only called once, and the identity of the array can change if you call alertService.clear , you'll probably have better luck putting a watch in your alert's link statement:

link: function(scope) {
  scope.$watchCollection(alertService.getAlerts, function(alerts) {
    scope.alerts = alerts;
  });
}

Since this method doesn't directly do any DOM manipulation, modern angular best-practice would probably be to implement this as a component instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM