Brian Triplett
Brian Triplett

Reputation: 3532

Angular Controller not updating when service updated

My view in my angular directive does not seem to update when the underlying data changes. I'm not sure if I'm missing a digest cycle or what but I can't seem to figure out what is happening

Directive:

(function(){
'use strict';
angular.module('app').directive('message', Message);
function Message() {
    var markup = '<div class="slds">'+
                        '<div ng-repeat="message in messageController.alerts">'+
                            '<div class="slds-box slds-theme--{{message.type}}">'+
                                '<a href="#" class="slds-float--right" ng-show="message.canDismiss"'+
                                  ' ng-click="messageController.closeAlert(message)">'+
                                    'Dismiss'+
                                '</a>'+
                                '<h2>'+
                                    '{{message.text}}'+
                                '</h2>'+
                            '</div>'+
                        '</div>'+
                    '</div>';

    return {
        restrict: 'E',
        controllerAs: 'messageController',
        controller: 'MessageController',
        template: markup,
        scope: {}
    };
}
})();

Controller:

(function(){
'use strict';
angular.module('app').controller('MessageController', MessageController);
MessageController.$inject = ['messageService'];
function MessageController(messageService) {
    var self = this;

    self.alerts = messageService.getMessages();

    self.closeAlert = function (message) {
        messageService.removeMessage(message);
    };
}})();

Service:

(function(){
'use strict';
angular.module('app').service('messageService', MessageService);
function MessageService() {
    var self = this;
    var messages = [];

    self.setMessage = function (message, clear){
        if (clear === true){
            self.clear();
        }

        messages.push(message);
    };

    self.getMessages = function(){
        return messages;
    };

    self.removeMessage = function(message){
        var messageIndex = messages.indexOf(message);
        if(messageIndex !== -1){
            messages.splice(messageIndex, 1);
        }
    };

    self.clear = function(){
        messages = [];
    };
}
})();

I'm letting the messages display be triggered off of an ng-disabled directive on a button so an example usage would be:

<message></message>

<!-- other markup -->

<button type="submit" ng-disabled="!(form.$valid &&
                                    !vm.arePaymentPeriodsExceeded())"
        ng-click="vm.saveStream()">
    Save
</button>

and then in the page controller

function arePaymentPeriodsExceeded() {

    var totalPeriods = calculateTotalPaymentPeriods();

    setPaymentExceededError(totalPeriods);

    return totalPeriods > vm.loanInfo.loanTerm;
}

function setPaymentExceededError(totalPeriods){

    if(totalPeriods > vm.loanInfo.loanTerm) {

        if(messageService.getMessages().indexOf(tooManyPaymentsMessage) === -1) {
            messageService.setMessage(tooManyPaymentsMessage);
        }

    } else {
        messageService.removeMessage(tooManyPaymentsMessage);
    }
}

The behavior is sporadic, sometimes the message directive shows a message and sometimes it does not. The odd thing is the enabling of the button works fine (in other words the method in the controller is being called to enable/disable the button), but the directive binding is not updating. Is there something happening that is "disconnecting" the service, controller, directive?

Upvotes: 2

Views: 85

Answers (2)

rupampatel
rupampatel

Reputation: 300

You need to refresh view by calling getMessages() every-time you perform some operation on messages.

self.alerts = messageService.getMessages() won't update automatically.

Controller:

 self.alerts = messageService.obj.messages;

Service:

var obj = {
    messages  :[]
}

self.clear = function(){
    obj.messages.length = 0;
};

Upvotes: 0

holtc
holtc

Reputation: 1820

When you call messgeService.clear(), you should be using messages.splice(0), as messages = [] points to a new object reference and you will lose any controller reference to the old messages array. messages.splice(0) will clear the array while maintaining the original object reference.

Upvotes: 1

Related Questions