How to configure ui-router for angular1 correctly?

Help us understand the nested routing ui-router. Here is a simple example.

There are 3 urls:

/main

/main/apples

/main/oranges

There is a navigation of two items: apples and oranges. It is only present on the /main/apples and /main/oranges pages and is used to switch between these pages. A div with this navigation should not reload when switching between these two sections.

angular.module('fruits', ['ui.router']);

angular.module('fruits').config(function($stateProvider, $urlRouterProvider, $locationProvider){

  $stateProvider.state({
      name: 'main',
      url: '/main',
      templateUrl: 'templates/main.html'
  });

  $stateProvider.state({
      name: 'main.oranges',
      url: '/oranges',
      templateUrl: 'templates/oranges.html'
  });

  $stateProvider.state({
      name: 'main.apples',
      url: '/apples',
      templateUrl: 'templates/apples.html'
  });

  $urlRouterProvider.otherwise('/');

  $locationProvider.html5Mode({
      enabled: true,
      requireBase: false
  });

});

Main.html:

<!-- Заголовок и текст главной страницы, которые должны присутствовать только на главной странице -->
<h1> Главная страница </h1>
<span> Содержимое главной страницы </span>

<!-- Навигация, которая должна присутствовать только на страницах /main/oranges и /main/apples и не перезагружаться при переходе между ними -->
<div class="navigation">
  <a ui-sref="main.oranges"> Яблоки </a>
  <a ui-sref="main.apples"> Апельсины </a>
</div>

<ui-view> </ui-view>

I need the /main/oranges and /main/apples pages to have no main page content, but still have navigation. Right now, the /main/oranges and /main/apples pages are both.


Thanks for the Grundy tip. Changed the code as follows:

Main.html:

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

App.js:

angular.module('fruits', ['ui.router']);

angular.module('fruits').config(function($stateProvider, $urlRouterProvider, $locationProvider){

  $stateProvider.state({
      name: 'main',
      url: '/main',

      views: {
        '': {
          templateUrl: 'templates/main.html',
        },

        'fruits-main@main': {
          templateUrl: 'templates/fruits-main.html',
        }
      }
  });

  $stateProvider.state({
      name: 'main.apples',
      url: '/apples',

      views: {
        '': {
          templateUrl: 'templates/apples.html',
        },
        'nav': {
          templateUrl: 'templates/nav.html',
        },
        'fruits-main': {
          abstract: true,
        }
      }
  });

  $stateProvider.state({
      name: 'main.oranges',
      url: '/oranges',

      views: {
        '': {
          templateUrl: 'templates/oranges.html',
        },
        'nav': {
          templateUrl: 'templates/nav.html',
        },
        'fruits-main': {
          abstract: true,
        }
      }
  });

  $urlRouterProvider.otherwise('/');

  $locationProvider.html5Mode({
      enabled: true,
      requireBase: false
  });

});

But one problem is not solved. Navigation is reloaded every time you move from one section to another. How be?


Apples.html

<h1> Яблоки </h1>
<p>Текст о яблоках</p>

Nav.html

<!-- Навигация, которая должна присутствовать только на страницах /main/oranges и /main/apples и не перезагружаться при переходе между этими разделами -->
<div class="navigation">            
    <a ui-sref="main.apples" ui-sref-active="active"> Яблоки </a>
    <a ui-sref="main.oranges" ui-sref-active="active"> Апельсины </a>             
    <div class="animation"></div>
</div>

Fruits-main.html

<h1>Главная страница</h1>
<p>Какой-то текст на главной странице</p>  

Css:

*{
  margin: 0;
  padding: 0;
}

.active{
  color: red !important;
}


@-webkit-keyframes go {
  from {
    left: 0px;
  }
  to {
    left: 500px;
  }
}


.animation{
  width: 50px;
  height: 50px;
  background: green;
  position: relative;
  left: 0;

  -webkit-animation: go 1s infinite alternate;
}
Author: user208795, 2016-08-23

1 answers

The problem is that the navigation block changes in each of the page states, even if it is not the same.

For the solution, you can enter some abstract parent state for these pages, in which you can set a template for navigation once.

It might look like this:

angular.module('fruits', ['ui.router']);

angular.module('fruits').config(function($stateProvider, $urlRouterProvider) {

  $stateProvider.state({
    name: 'main',
    url: '/main',

    views: {
      '': {
        templateUrl: 'main.html',
      },

      'fruits-main@main': {
        templateUrl: 'fruits-main.html',
      }
    }
  });
  $stateProvider.state('main.fruits', {
    abstact: true,
    url: '',
    views: {
      '': {
        template: '<ui-view></ui-view>'
      },
      'nav': {
        templateUrl: 'nav.html',
      }
    }
  });

  $stateProvider.state({
    name: 'main.fruits.apples',
    url: '/apples',

    views: {
      '': {
        templateUrl: 'apples.html',
      },
      'fruits-main@main': {
        abstract: true
      }
    }
  });

  $stateProvider.state({
    name: 'main.fruits.oranges',
    url: '/oranges',

    views: {
      '': {
        templateUrl: 'oranges.html',
      },
      'fruits-main@main': {
        abstract: true
      }

    }
  });

  $urlRouterProvider.otherwise('/main/oranges');

});
/* Styles go here */

* {
  margin: 0;
  padding: 0;
}
.active {
  color: red !important;
}
@-webkit-keyframes go {
  from {
    left: 0px;
  }
  to {
    left: 500px;
  }
}
.animation {
  width: 50px;
  height: 50px;
  background: green;
  position: relative;
  left: 0;
  -webkit-animation: go 1s infinite alternate;
}
<script data-require="[email protected]" data-semver="1.5.9" src="//code.angularjs.org/1.5.8/angular.js"></script>
<script data-require="[email protected]" data-semver="0.3.1" src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.1/angular-ui-router.js"></script>
<div ng-app="fruits">
  <div ui-view></div>

  <script type="text/ng-template" id="main.html">
    <div ui-view="fruits-main"></div>
    <div ui-view="nav"></div>
    <ui-view></ui-view>
  </script>
  <script type="text/ng-template" id="nav.html">
    <!-- Навигация, которая должна присутствовать только на страницах /main/oranges и /main/apples и не перезагружаться при переходе между этими разделами -->
    <div class="navigation">
      <a ui-sref="main.fruits.apples" ui-sref-active="active"> Яблоки </a>
      <a ui-sref="main.fruits.oranges" ui-sref-active="active"> Апельсины </a> 
      <div class="animation"></div>
    </div>
  </script>
  <script type="text/ng-template" id="apples.html">
    <h1> Яблоки </h1>
    <p>Текст об яблоках</p>
  </script>
  <script type="text/ng-template" id="fruits-main.html">
    <h1>Главная страница</h1>
    <p>Какой-то текст на главной странице</p>
  </script>
  <script type="text/ng-template" id="oranges.html">
    <h1> Апельсины </h1>
    <p>Текст об апельсинах</p>
  </script>
</div>
 1
Author: Grundy, 2016-08-25 06:36:32