Message appears in modal and page at the same time

Asked

Viewed 460 times

0

I created a "message center" in Angularjs that injects messages on the screen. The message always appears when an error occurs in REST operations or success. This is done by an Interceptor that checks if the response has a message header, if it is injected into the message and type, and the directive prints on the screen.

The problem is that the message appears in Modal, which is right, and also appears on the page that called the modal the first time I open the page the other times does not appear.

First time saving a user: inserir a descrição da imagem aqui

Second time, after closing the modal and the message that appeared on the listing screen: inserir a descrição da imagem aqui

Interceptor (which is configured in $httpProvider):

angular.module('app').factory('notificationInterceptor', function ($q, AlertService) {
    return {
        responseError: function(response) {
            addMessage(response);
            return $q.reject(response);
        },
        response: function(response) {
            addMessage(response);
            return response;
        }
    };

    function addMessage(response){
         var alert = response.headers('X-applicationMessage');
         if (angular.isString(alert)) {
            var mensagens = response.data.mensagens ;
            var timeout = 10000; 
            if(mensagens!= undefined){
                        mensagens.forEach(function(element, index, array) {
                            AlertService.add(element.messageType, element.body);
                    });
            }
         }
    }

Provider

'use strict'

angular.module('app').provider('AlertService',
        function() {
            this.$get = [ function() {
                var alerts = [];

                var exports = {
                    add : add,
                    clear : clear,
                    get : get
                }

                function clear() {
                    alerts = [];
                }

                function get() {
                    return alerts;
                }

                function add(type, msg) {
                    var alert = {
                        type : type,
                        msg : msg,
                    };

                    alerts.push(alert);

                    return alert;
                }

                return exports;
            } ];
        });

Directive

'use strict';
angular
        .module('app')
        .directive(
                'mcAlert',
                function(AlertService) {
                    return {
                        restrict : 'E',
                           template:  '<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>',
                        controller : [ '$scope', function($scope) {
                            $scope.alerts = AlertService.get();

                            $scope.$on('$destroy', function() {
                                AlertService.clear();
                            });

                            $scope.closeAlert = function(index)  {
                                $scope.alerts.splice(index, 1);
                            }
                        }]
                    }
                });
  • How is the html of the modal and the page that calls the modal?

  • Do you want to see it all? or just the directive part?

  • Only the party having the directive

  • I called it this way: <mc-Alert />. If you want the code that is generated I put.

  • I wanted to know if you actually use the directive on both the modal and the page, but I think it’s kind of obvious that you do. What I think is happening here is that you have a Service that feeds the Alerts in more than one place. Since Service is a single instance it must be passing the list of Alerts to the two places you use the directive

  • @Viniciuszaramella is exactly what you said. However the strange is the problem only occurs the first time, in the other the alert only appears in modal.

  • I think this has to do with the $Stroy you created. By calling it the two pages lose reference to the list that is within Alertservice. When you open the modal again it picks up the reference again, but the main page does not.

  • I can take the $Scope from the current page and put the alerts inside it through the directive?

  • @Viniciuszaramella I can get $Scope from the current controller and put the alerts inside it through the directive?

  • I believe you will need to create an attribute in your directive that receives a function from the controller Scope that is making the request to update the list of Alerts. I’ll try to make an answer.

Show 5 more comments

1 answer

1


I think the best way to solve your problem without starting to mix the Copes is to put in your Alertservice who is the callback that it should notify when Alertservice receives notifications.

One way to do this would be to keep a list of callbacks in Alertservice and delete them in Destroy, another would be to keep an id by callback and try to access them by this id.

Trying to exemplify the idea.

'use strict'

angular.module('app').provider('AlertService',
        function() {
            this.$get = [ function() {
                var alerts = [];
                var callbacks = [];
                var exports = {
                    add : add,
                    clear : clear,
                    get : get
                }

                function clear() {
                    alerts = [];
                    unregisterLastCallback();
                }
                function unregisterLastCallback(){
                   callbacks.remove(<lasts>);
                }
                function registerCallback(callback){
                   callbacks.push(callback);
                }

                //function get() {

                  //  return alerts;
                //}

                function add(type, msg) {
                    var alert = {
                        type : type,
                        msg : msg,
                    };

                    alerts.push(alert);
                    notify();
                    return alert;
                }

                function notify(){
                    callbacks.<PegueUltimoDaLista>(alerts)//passar cópia de alerts;

                 }

                return exports;
            } ];
        });

Then the directive would look like this

'use strict';
angular
        .module('app')
        .directive(
                'mcAlert',
                function(AlertService) {
                    return {
                        restrict : 'E',
                           template:  '<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>',
                        controller : [ '$scope', function($scope) {

                            var updateCallback() = function(alerts){
                                $scope.alerts = alerts// certificar de que é uma cópia.
                            }                                      


                            AlertService.registerCallback( updateCallback);
                            $scope.$on('$destroy', function() {
                                AlertService.clear();
                            });

                            $scope.closeAlert = function(index)  {
                                $scope.alerts.splice(index, 1);
                            }
                        }]
                    }
                });

I think the implementation using a stack of callback might be very confusing and easy to get wrong...but the idea I wanted to pass is that you’ll have to have some way to identify in the Service or in the Controller which directive you’re referring to so that only it be notified when alerts arrive.

  • I did the implementation and it worked. Will the callback be registered at the moment the controller is called? If so, the listing controller is the first, and the modal controller is the last. Correct?

  • That’s it. When the view is rendered in the angular Digest cycle it calls the directive controller and records the event. This could be done in the link instead of the controller in the directive (I think it would be more correct) from the point of view of responsibilities.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.