2

I have an issue with my angularjs app on the events and listeners.

My application has an index.html file like this:

<body ng-app="ua.myApp">
    <!-- Navigation bar -->
    <ng-include src="'app/common/navbar/navbar.tpl.html'"></ng-include>
    <ng-view></ng-view>

    <script type="text/javascript" src="app/common/navbar/navbar.js"></script>
    <script type="text/javascript" src="app/part1/part1.js"></script>

</body>

In the navbar controller I have a listener:

console.log('Setup event listner - navBar: update');
$scope.$on('navBar: update', function() {
    if (uaContext.loginStatus.get() == true) {
        $scope.setLoggedInBar();
    } else {
        $scope.setLoggedOutBar();
    }
}); 

And in the part1 app I broadcast an event:

function ($scope, $rootScope, $routeParams, uaContext) {
    console.log('Send event listner - navBar: update');
    $scope.$on('$routeChangeSuccess', function () {
        uaContext.productId.set($routeParams.productId);
        uaContext.appName.set('part 1');
        $rootScope.$broadcast('navBar: update');
    });
}

The dependencies in myApp are in this order:

var myApp = angular.module('ua.myApp', [
    'ua.NavBar',
    'ua.Part1']);

It's working fine. Console log:

Setup event listner - navBar: update (nav_bar.js)
Send event listner - navBar: update (part1.js)

The issue is that sometimes the event is sent by part1 app before the listener in navbar is operational. So we get this situation:

Send event listner - navBar: update (part1.js)
Setup event listner - navBar: update (nav_bar.js)

Thus the nav bar is not updated.

Do you know how I can fix this issue? Maybe I can emit the event in another event than routeChangeSuccess but I didn't found the documentation on the events.

Thank you

Michael Benford
  • 14,044
  • 3
  • 60
  • 60
Julio
  • 2,493
  • 4
  • 33
  • 53

1 Answers1

1

You can listen for the $includeContentLoaded event in the $scope that applies to where the ng-include is set.

Another solution, rather than relying on timing events, is to create a service that can be injected into both controllers which can be used to share navigation state between the two. That way, even if an event is fired before the navbar controller is instantiated, the navbar controller can read the appropriate state from the shared service.

jandersen
  • 3,551
  • 22
  • 23
  • In fact the data are already shared thanks to the uaContext service. One solution could be to add a watch on the variables of this service but I will have to use several variables in the service. So I will have to put a watch on all elements requested in the service? Is this the best way? – Julio Aug 28 '13 at 11:43
  • You've already got a service, nice work! Yeah, I think if you have different views that need to respond to the variables (state) of that service then exposing those as properties of the service that can be watched is a reasonable way to go. – jandersen Aug 28 '13 at 12:54
  • Ok but is it efficient to watch several variables in a service? I have 10 variables to watch. One workaround could be to add a variable `modified` in this service and modify it after each modification of a variable in the service. Then I will be able to watch this variable. The other workaround is to use event. But I am not able to catch the event if the included nav-bar is loaded after the broadcast of the event. The `includeContentLoaded` event is not able to solve this issue as I have to send the event from the ng-view Part1 to the included component nav-bar – Julio Aug 28 '13 at 13:43
  • yeah, the `includeContentLoaded` event would be a place you could **dispatch your event** ensuring your navbar is loaded and its handler will receive it. If you're worried about the efficiency of the watches, you can NOT watch in your nav controller but simply check the nav service state at startup while STILL listening for those events. This way the nav bar gets the correct state from the service at startup (even if it has missed events) but will still listen for events to stay in sync with state (without using watches). – jandersen Aug 28 '13 at 15:01
  • BTW... as far as overall efficiency... watching 10 variables shouldn't be a problem. See Misko's seminal post on the topic: http://stackoverflow.com/questions/9682092/databinding-in-angularjs All your databinding expressions in templates are essentially watches as well so angular has to be able to handle many more than just 10 efficiently – jandersen Aug 28 '13 at 15:44