Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I prevent reload on named view, when state changes? AngularJS UI-Router

Tags:

I'm using the excellent ui-router module in my application. As part of this, I'm using named views to manage the 'dynamic sub-navigation' I have in the app.

Consider the following:

$urlRouterProvider.otherwise('/person/list');  $stateProvider     .state('person', {         url: '/person',         abstract: true,     })     .state('person.list', {         url: '/list',         views: {             "main@": {                 templateUrl: "person.list.html",                 controller: 'PersonListController'             }         }     })     .state('person.details', {         url: '/{id}',         views: {             'main@': {                 templateUrl: "person.details.html",                 controller: 'PersonController'             },             'nav@': {                 templateUrl: "person.nav.html",                 controller: 'PersonNavController'             }         }     }); 

When users first visit the app, they are presented with a list of people. When they click on a person, they are taken to the details page. Pretty basic stuff. Here's the markup if it helps...

<div>     <aside ui-view="nav"></aside>     <div ui-view="main"></div> </div> 

However, the PersonNavController calls a REST service to get a list of people, so when viewing a person, the user is able to navigate sibling elements. Using the method above causes the template and controller to re-render, thus causing a delay after every click, despite the content never changing.

Is there a way to keep the 'nav@' view loaded, and only refresh the 'main@' view?

like image 942
mortware Avatar asked May 09 '14 15:05

mortware


1 Answers

The way I am using ui-router in this scenarios is: move the views to the least common denominator.

Other words: In case that ui-view="nav" is shared among all the details and is the same for all of them (because it should be loaded only once) - it should be part of the list state (parent of the detail state)

the parent state defintion would be adjusted like this:

.state('person.list', {     url: '/list',     views: {         "main@": {             templateUrl: "person.list.html",             controller: 'PersonListController'         }         // here we target the person.list.html         // and its ui-view="nav"         '[email protected]': {             templateUrl: "person.nav.html",             controller: 'PersonNavController'         }     } 

So where is the trick? In the power of the angular ui-router. We can, during each state defintion, target the current view. Now, the nav view is part of the list state definition - i.e. it will not be reloaded during the detail switching (also check here for more explanation)

We just have to use the defined naming conventions, see:

  • View Names - Relative vs. Absolute Names

Few cited lines from the mentioned documentation:

views: {     ////////////////////////////////////     // Relative Targeting             //     // Targets parent state ui-view's //     ////////////////////////////////////      // Relatively targets the 'detail' view in this state's parent state, 'contacts'.     // <div ui-view='detail'/> within contacts.html     "detail" : { },                  // Relatively targets the unnamed view in this state's parent state, 'contacts'.     // <div ui-view/> within contacts.html     "" : { },       ///////////////////////////////////////////////////////     // Absolute Targeting using '@'                      //     // Targets any view within this state or an ancestor //     ///////////////////////////////////////////////////////      // Absolutely targets the 'info' view in this state, 'contacts.detail'.     // <div ui-view='info'/> within contacts.detail.html     "[email protected]" : { }      // Absolutely targets the 'detail' view in the 'contacts' state.     // <div ui-view='detail'/> within contacts.html     "detail@contacts" : { } 
like image 76
Radim Köhler Avatar answered Oct 12 '22 15:10

Radim Köhler