mattevigo
mattevigo

Reputation: 25

Angular directive's controller initialized twice

I have a project based on https://github.com/driftyco/ionic-starter-sidemenu

I made a directive rsNotification for handle upcoming MQTT messages

rsNotification.js

    (function (angular) {
    console.log("*** rsNotification module init");

    var rsNotificationModule = angular.module('rsNotification', ['rsMessenger']);

    var NotificationController = ['$log', '$scope', 'MessengerService', function ($log, $scope, MessengerService) {

        console.log("*** NotificationController init", $scope);
        $scope.badgeCount = 0;

        $scope.$on('rsMQTT.message', function (event, message) {
            $scope.badgeCount++;
            MessengerService.post(message.toString());
        });
    }];

    rsNotificationModule.directive('rsNotification', function () {
        console.log("*** Loading template");
        return {
            restrict: 'E',
            templateUrl: 'templates/rs-notification.html',
            controller: NotificationController
        };
    });

})(angular);

In app.js I have the following configuration for starter module

$stateProvider
    .state('app', {
        url: "/app",
        abstract: true,
        templateUrl: "templates/menu.html",
        controller: 'AppCtrl'
    })
    .state('app.dashboard', {
        url: "/dashboard",
        views: {
            'menuContent': {
                templateUrl: "templates/dashboard.html",
                controller: 'DashboardController'
            }
        }
    })

// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/dashboard');

...and the directive rs-notification.html

<button class="button button-clear">
    <span class="fa fa-flag-o fa-2x"></span>
</button>
<span class="rs-badge danger" ng-show="badgeCount > 0">{{badgeCount}}</span>

The rs-notification directive is used in the menu.html template inside the ionic-nav-bar

<ion-side-menus enable-menu-with-back-views="false">

    <ion-side-menu-content>

        <ion-nav-bar class="rs-header">
            <ion-nav-back-button>
            </ion-nav-back-button>

            <ion-nav-buttons side="left">
                <button class="button button-icon button-clear ion-navicon color-primary-light" menu-toggle="left"></button>
            </ion-nav-buttons>

            <ion-nav-buttons side="right">
                <div>
                    <button class="button button-clear" ng-click="showCart()">
                        <span>{{cartName}}</span>
                        <span class="fa fa-shopping-cart fa-2x color-primary-dark"></span>
                    </button>
                </div>
                <rs-notification></rs-notification>
            </ion-nav-buttons>

        </ion-nav-bar>

        <ion-nav-view name="menuContent"></ion-nav-view>

    </ion-side-menu-content>

    <!-- Left menu... -->

</ion-side-menus>

The problem is that rsMQTT.message event is fired twice for each upcoming message, as matter of fact the NotificationController is instatiated twice as you can see in the console log:

*** rsNotification module init
*** NotificationController init
*** NotificationController init
*** Loading template

Upvotes: 2

Views: 619

Answers (1)

Content of ion-nav-buttons element is recompiled into another element and then injected into $ionViewController. Because of that, it is possible that your directive is in fact compiled (and the controller is instantiated) twice (or more). To get around that, you should move your logic into a service and leave that element as a nutshell only.

Upvotes: 1

Related Questions