Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - templating with sub-routes

I'm quite new to Angular.js and I can't seem to figure out how to solve my problem.

The app consists of three main tabs which are also top-level routes, ie.

#/home
#/inbox
#/products

The current route-configuration looks something like this (coffeescript):

$routeProvider.
  when('/home', templateUrl: 'home.html').
  when('/inbox', templateUrl: 'inbox.html').
  when('/inbox/:thread_id', templateUrl: 'inbox.html', controller: 'MessagesCtrl').
  otherwise(redirectTo: '/inbox')

Now, the problem is the inbox view.

The inbox view (inbox.html) is a split column template with a list of message-threads to the left and the messages of the selected thread to the right:

 --------------------------
| Navigation               |
 --------------------------
|         |                |
| Threads |    Messages    |
|         |                |
|         |                |

The list of threads should be visible for all #/inbox routes no matter if a thread has been selected or not.

As you can see from the routes, the inbox view is a separate template (inbox.html) which is loaded both when a thread is selected and when it's not. This makes Angular re-render the entire view each time a thread is selected, which also causes the thread-list (to the right) to re-render and loose its scroll-position.

I would like to keep the thread-list from re-render whenever a thread is selected and I can't seem to figure out how to organize my routes/templates in order to achieve this.

Any suggestions would be greatly appreciated!

like image 929
sewa Avatar asked Jan 27 '13 13:01

sewa


2 Answers

Please check this issue, I believe your problem is exactly the same.

If you change the URL path, everything inside the ng-view will be re-rendered and there's no way to avoid that. However, if you set the reloadOnSearch to false on the route configuration and then use links like /inbox?id=1, the ng-view will not be re-rendered. This is probably the best solution for your problem, you can use deep linking and avoid re-renders.

Regarding the reloadOnSearch property, angularjs documentation states:

[reloadOnSearch=true] - {boolean=} - reload route when only $location.search() changes.

If the option is set to false and url in the browser changes, then $routeUpdate event is broadcasted on the root scope.

You just need to listen for the $routeUpdate event to update the information inside the inbox controller, like this:

app.controller('InboxCtrl', function($scope, $routeParams) {      
    $scope.$on('$routeUpdate', function(value) {
        // update the model/$scope here based on the $routeParams info...
    });    
});

jsFiddle example: http://jsfiddle.net/bmleite/ZB56n/

like image 103
bmleite Avatar answered Oct 22 '22 03:10

bmleite


Thank you for your suggestions. However, I was able to solve it using this technique:

http://www.bennadel.com/blog/2441-Nested-Views-Routing-And-Deep-Linking-With-AngularJS.htm https://github.com/bennadel/AngularJS-Routing

It's was bit more complicated to implement, but for my case I think it is worth it in the end

like image 30
sewa Avatar answered Oct 22 '22 02:10

sewa