Angular UI-Router - Refresh lazy-loaded nested ui-view on state change


I'm new to using ui-router and am having some difficulty with a lazy loaded nested ui-view. I've tried a number of things and though I imagine I've come close, I can't quite get it to work, so whoever fixes the plunker shared below will be awarded the correct answer.

Plunker

-Firstly, require.js bootstraps the main application, and index.html contains two ui-views, one for the navigation, and one for the main content section. The main content section contains various portfolio items (Test1 in plnkr) that are lazy loaded (with ocLazyLoad) into the main content section when one is selected.

-The main app module defines the various states in its config method, including a state to load the portfolio item according to its ID and based on a naming convention.

-When Test1 is clicked, its main module is lazy loaded, and this module defines its own states, and Test1 has its own index.html with its own nested ui-view. Worth noting is that I've also had to use this module's run method to run a function that wraps $state.go in $timeout, to get template content to appear in the nested ui-view when Test1 is initially clicked. This is hackish and undoubtedly not the right approach and perhaps the source of the issue, as we'll see shortly. I also tried to put the $state.go in a service but it didn't make a difference as I ultimately ran into the same problem.

-Finally, here's where things break. If from inside Test1, you click on Home in the main nav, then try clicking on Test1 again, the template content that appeared previously in the nested ui-view doesn't appear (obviously, since the module's run function only runs once). It's easy to make it reappear by manually clicking on a link that reloads the state, but obviously this isn't desirable.

TL/DR -- Home -> Click on Test1 -> Working! -> Click Home -> Click Test1 -> Breaks!

Main app module and states:

(function() {

  angular.module('myApp', [
  'ui.router',
  //'door3.css',
  'oc.lazyLoad'
])
.config(function($ocLazyLoadProvider, $stateProvider, $urlRouterProvider) {

  $urlRouterProvider.otherwise('/');

  $stateProvider
    .state('root', {
      url: '/',
      views: {
        'nav': {
          templateUrl: 'views/static/nav.html'
        },
        'content': {
          templateUrl: 'views/portfolio.html'
        }
      }
    })
    .state('root.home', {
      url: 'home',
      views: {
        '[email protected]': {
          templateUrl: 'views/portfolio.html'
        }
      }
    })
    .state('root.about', {
      url: 'about',
      views: {
        '[email protected]': {
          templateUrl: 'views/about.html'
        }
      }
    })
    .state('root.portfolio', {
      url: ':id',
      views: {
        '[email protected]': {
          // css: function($stateParams) {
          //   return '/portfolio/' + $stateParams.id + '/css/master.css';
          // },
          templateUrl: function($stateParams) {
            return 'portfolio/' + $stateParams.id + '/index.html';
          },
          resolve: {
            load: function($stateParams, $ocLazyLoad) {
              return $ocLazyLoad.load({
                files: ['portfolio/' + $stateParams.id + '/js/mainModule.js']
              });
            }
          }
        }
      }
    });

});

})();

Lazy loaded Test1 main module and states:

(function() {

  angular.module('testingApp', [{
  files: [
    'portfolio/testing/controllers/testingCtrl.js'
  ]
}])
.config(function($stateProvider, $urlRouterProvider) {

  $urlRouterProvider.otherwise('/');

  $stateProvider
    .state('root.portfolio.testing', {
      url: '/',
      views: {
        '[email protected]': {
          templateUrl: 'portfolio/testing/views/testfile.html',
          controller: 'testingCtrl',
          controllerAs: 'test'
        }
      }
    })
})
.run(function($state, $timeout) {
  $timeout(function() {
    $state.go('root.portfolio.testing');
  }, 0);
});

})();

I am not sure what you are trying to achieve but putting $state.go into run block was a reason why it worked the first time and any other consecutive time.

The reason is that run block is run only once at the time when module loads and module is loaded only once.

To fix this move $state.go call into testingCtrl while adding $state as a dependency injection

See my fixed plunker.