Reputation: 721
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()">×</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
Upvotes: 0
Views: 1099
Reputation: 5225
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.
Upvotes: 1
Reputation: 114
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;
}
})
Upvotes: 1