javascript - How to broadcast path changes to all views in an AngularJS app? - Stack Overflow

I have an AngularJS single-page app displaying 3 views (which are actually 3 directives). To illustrate

I have an AngularJS single-page app displaying 3 views (which are actually 3 directives). To illustrate my question, let's assume my UI is identical to that of GMail and that my 3 views are:

  • Navigation Pane (left) -- where GMail displays folders like "Inbox", "Drafts"...
  • Toolbar (top right) -- where GMail displays buttons
  • Content Pane (bottom right) -- where GMail displays messages

These 3 views need to update themselves whenever the path changes. For example:

  • The Navigation Pane needs to highlight a specific item.
  • The Toolbar needs to show/hide certain buttons.
  • The Content Pane needs to load and display specific data from the server.

What's the best way to do this in AngularJS?

So far, I have:

  1. Ruled out the use of $routeProvider.when() because I need to update three views, and $routeProvider only supports one ngView.
  2. Created a SERVICE that watches the current path and uses $rootScope.$broadcast() to warn the controllers that the path changed.
  3. (OR, IN LIEU OF #2) Created a CONTROLLER that does the same as #2.
  4. Caught the event broadcasted by #2 or #3 with $scope.$on() (I do this in a view controller).

This kind of works, but I have several issues:

  • The "path change" event is often broadcasted BEFORE my event listeners are in place, especially at initial page load. This is probably due to the fact that my view templates are loaded from the server and the listeners can't be set up before the templates have finished loading.
  • Isn't there a more efficient/automated way to watch for path changes in AngularJS? (See my code below, it seems pretty "manual".)
  • Does the code that watches for path changes belong in a SERVICE or in CONTROLLER? (I'd lean towards a service, since a controller is more to add behavior to a view.)
  • How to guarantee that my views will catch the "path changed" event? Should I use an event at all? (maybe I could store the path in a service, and have my views watch the service instead?)

My code to watch for path changes (I put this in a service or in a controller):

var watchExpression = function() { return $location.path(); };
var listener = function(newPath, oldPath) {
    // Broadcast event on $rootScope
    $rootScope.$broadcast('PathChanged', newPath);
};
$rootScope.$watch(watchExpression, listener);

Then, in a view controller, I catch the event:

$scope.$on('PathChanged', function(event, path) {
    // Update view based on new path.
});

Any help appreciated. Thanks.

I have an AngularJS single-page app displaying 3 views (which are actually 3 directives). To illustrate my question, let's assume my UI is identical to that of GMail and that my 3 views are:

  • Navigation Pane (left) -- where GMail displays folders like "Inbox", "Drafts"...
  • Toolbar (top right) -- where GMail displays buttons
  • Content Pane (bottom right) -- where GMail displays messages

These 3 views need to update themselves whenever the path changes. For example:

  • The Navigation Pane needs to highlight a specific item.
  • The Toolbar needs to show/hide certain buttons.
  • The Content Pane needs to load and display specific data from the server.

What's the best way to do this in AngularJS?

So far, I have:

  1. Ruled out the use of $routeProvider.when() because I need to update three views, and $routeProvider only supports one ngView.
  2. Created a SERVICE that watches the current path and uses $rootScope.$broadcast() to warn the controllers that the path changed.
  3. (OR, IN LIEU OF #2) Created a CONTROLLER that does the same as #2.
  4. Caught the event broadcasted by #2 or #3 with $scope.$on() (I do this in a view controller).

This kind of works, but I have several issues:

  • The "path change" event is often broadcasted BEFORE my event listeners are in place, especially at initial page load. This is probably due to the fact that my view templates are loaded from the server and the listeners can't be set up before the templates have finished loading.
  • Isn't there a more efficient/automated way to watch for path changes in AngularJS? (See my code below, it seems pretty "manual".)
  • Does the code that watches for path changes belong in a SERVICE or in CONTROLLER? (I'd lean towards a service, since a controller is more to add behavior to a view.)
  • How to guarantee that my views will catch the "path changed" event? Should I use an event at all? (maybe I could store the path in a service, and have my views watch the service instead?)

My code to watch for path changes (I put this in a service or in a controller):

var watchExpression = function() { return $location.path(); };
var listener = function(newPath, oldPath) {
    // Broadcast event on $rootScope
    $rootScope.$broadcast('PathChanged', newPath);
};
$rootScope.$watch(watchExpression, listener);

Then, in a view controller, I catch the event:

$scope.$on('PathChanged', function(event, path) {
    // Update view based on new path.
});

Any help appreciated. Thanks.

Share Improve this question asked Aug 10, 2012 at 18:44 AngularChefAngularChef 14.1k9 gold badges55 silver badges69 bronze badges 2
  • 1 Found one improvement: instead of watching path changes manually like I did, it seems better to catch the native $locationChangeSuccess event: $rootScope.$on('$locationChangeSuccess', function(event, newUrl, oldUrl) { // Do something with newUrl ... }); – AngularChef Commented Aug 10, 2012 at 19:59
  • I ended up using neither a SERVICE nor a CONTROLLER, but a config function which watches for the native $locationChangeSuccess event and updates a $rootScope.path variable when that event happens. Then, my path-aware controllers watch the $rootScope.path variable and when it changes, they use $rootScope.pathEnv (an custom object storing environment variables, which is recalculated whenever the path changes) to update themselves appropriately. – AngularChef Commented Aug 10, 2012 at 20:51
Add a ment  | 

1 Answer 1

Reset to default 5

Your final version seems fine with the locationChangeSuccess, but for others reading this, I think you ruled out the $routeProvider too quickly. You can have one ng-view for the main content pane that changes with the path, and then other independent ("static") controllers/templates for the navigation pane and toolbar.

Now to listen to route changes in these other 2 controllers:

$rootScope.$on('$routeChangeSuccess', function(evt, cur, prev) {
    ...do what you have to do here, maybe set a $rootScope.path as you did
})

All using native Angular functionality. I actually do this in http://provok.in, a website I built using Angular, and I have a similar layout (well, not exactly, but I have "static" sections and an ng-view for the main content, dynamically updated based on the path, by the routeProvider).

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744662988a4586576.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信