8

This question is based on "How can I persist sibling ui-views when changing state" (plunker).

I try to keep a view (content) unchanged, when I change the state in the main navigation (mainNav).

The content should only be set by the sub navigation, and remain when changing the main navigation.

Is there a possibility to remain a view in ui-router, even if the state is left?

angular.module('MyApp', [
  'ui.router'
])
  .config(function($stateProvider, $urlRouterProvider) {

  $urlRouterProvider.otherwise('/');

  $stateProvider
    .state('index', {
      url: '/',
      views: {
      '@': {
        templateUrl: 'layout.html'
      },
      'mainNav@index': {
        template: '<a ui-sref="Main3">Main3 - with sub</a><br />'
                + '<a ui-sref="Main4">Main4 - with sub</a>'
      },
      'subNav@index' : {
        template: '<p>This is the sub navigation</p>'
      }, 
      'content@index': {
        template: '<p>Content shared for MAINs</p>'
      }
    }
  })
  .state('Main3', {
    parent: 'index', 
    url: '/Main3',
    views: {
      /*'mainNav': {

      },*/
      'subNav': {
        template: '<a ui-sref="Main3.Sub1">Main3.Sub1</a><br />'
        + '<a ui-sref="Main3.Sub2">Main3.Sub2</a>'
      }
    }
  })
  .state('Main4', {
    parent: 'index', 
    url: '/Main4',
    views: {
      'subNav': {
        template: '<a ui-sref="Main4.Sub1">Main4.Sub1</a><br />'
        + '<a ui-sref="Main4.Sub2">Main4.Sub2</a>'
      }
    }
  })

   .state('Main3.Sub1', {
    url: '/Sub1',
    views: { 'content@index': { template: 'Content of Main3.Sub1' } }
  })
  .state('Main3.Sub2', {
    url: '/Sub2',
    views: { 'content@index': { template: 'Content of Main3.Sub2' } }
  })
  .state('Main4.Sub1', {
    url: '/Sub1',
    views: { 'content@index': { template: 'Content of Main4.Sub1' } }
  })
  .state('Main4.Sub2', {
    url: '/Sub2',
    views: { 'content@index': { template: 'Content of Main4.Sub2' } }
  })

});

I found Persist state when changing to another state, but it doesn't solve the problem completely. The state is persistent, but there is no consideration of remaining a view consistent when navigating to a different state.

Community
  • 1
  • 1
Stefan
  • 1,041
  • 1
  • 14
  • 28

2 Answers2

1

Yes it is and it's quite easy however it has its limitation : store the data you need in the parent's scope.

$state.state('parent', {
     controller:'ParentController'
});

$state.state('parent.child1', {
    controller:'ChildController'
});

$state.state('parent.child2', {
    controller:'ChildController2'
});
// in Parent controller
$scope.context = {};// it important to create a intermediary field that will store the data, otherwise you might have a problem with scopes inheritance

// in Child controller
$scope.context.toto = 'titi';

// in other child controller $scope.context.toto = 'woof';

Note : i don' know if this will work if you use controllerAs syntax.

I personnally use it for a multi page form with next/back buttons in it.

Walfrat
  • 5,363
  • 1
  • 16
  • 35
  • Edit seems to be blocked... i forgot one thing : the limitation : this way means that the parent is a bit tied to its child since it provided some fields and child must be aware of each other in order to not have any conflict. A good way to resolve this would be for each child to store their state in a $scope.context.[child's state name]. – Walfrat Apr 18 '16 at 08:33
1

Walfrat's answer seems correct. I'm just trying to elaborate, and maybe understand what you're looking for. Here's what I think you're asking for:

// app.js 
...
$stateProvider
  .state('nav', {
    url: '/',
    templateUrl: 'app/templates/nav.html',
    controller: 'NavCtrl as nav',
    abstract: true
  })
  .state('nav.subNav', {
    url: 'subNav/',
    templateUrl: 'app/templates/subNav.html',
    controller: 'subNavCtrl as subNav',
    abstract: true
  })
  .state('nav.subNav.index', {
    url: 'index',
    templateUrl: 'app/templates/index.html',
    controller: 'IndexCtrl as index'
  });
$urlRouterProvider.otherwise('/subNav/index');
...

In this example, you can set the default view by including abstract: true in the nav state (note: I've never tried it three states deep, but it works with two states). This may give you the effect you are looking for.

As for having sub-navigations as views, it's should be possible, but I'm not sure if it's recommended to have deep nested views like that. Is this close to what you're looking for?

Onyooo
  • 105
  • 1
  • 10
  • abstract just make it impossible to navigate to, this has some utilty but has not really anything relevant with what the OP ask. – Walfrat Apr 18 '16 at 11:30
  • Exactly. By setting the abstract property you can have a nav bar-like parent view on your page. It will be there when you visit any of the child views. I'm not sure why this is not relevant. I am using this method in the project I'm currently working on. – Onyooo Apr 18 '16 at 12:48
  • just saying that's it's not relevant about what the OP asked. – Walfrat Apr 18 '16 at 13:09
  • You must know more about this than I do. This method produces exactly what I think the OP was asking for. I'd be happy to learn _why_ it's not relevant if you have time. – Onyooo Apr 18 '16 at 13:32
  • because what you said is the same as me, except the abstract part which does not concern the OP. However that just my opinion, furthermore i said that i don't know if it works fine with ctrlAs syntax because i don't think that controller inherits between them as the scope do. If you know about this, tha's definitively something relevant. – Walfrat Apr 18 '16 at 13:36
  • Ok fair enough. I did mention that your solution is likely the correct one. I know this configuration does work with controllerAs, because I am currently using it. – Onyooo Apr 18 '16 at 13:49
  • But does it works for OP problems `How can I persist sibling ui-views when changing state` ? – Walfrat Apr 18 '16 at 14:05
  • That is a good question. I was posing this as an option, while asking for more information. I hope the OP considers this option, but understand if it doesn't solve their problem. I just think it's close to what they want, and so is your answer. – Onyooo Apr 18 '16 at 14:09