Вложенное состояние ui-router без вложенного представления?

Мне интересно, возможно ли иметь вложенное состояние без вложенного представления. Предположим, что у меня есть эта настройка:

App.config(function($stateProvider, $urlRouterProvider) {
    //
    //
    // Now set up the states
    $stateProvider
    .state('index', {
        url: "/index",
       templateUrl: "views/home.html",
        controller: "MainController",
        ncyBreadcrumb: {
            label: 'Home'
        }
    })
    .state('About', {
        url: "/about",
        templateUrl: "views/about.html",
        controller: "AboutController",
        ncyBreadcrumb: {
            label: 'About',
            parent: 'index'
        }
    })
    .state('us', {
        url: "/us",
        templateUrl: "views/us.html",
        controller: "UsController",
        parent: 'about',
        ncyBreadcrumb: {
            label: 'Us'
        }
    })
    //
    // For any unmatched url, redirect to /home
    $urlRouterProvider.otherwise("/index");

});

Когда я навещаю /about, я получаю о странице. Когда я навещаю /about/us, я все равно получаю о странице с страницей us, загруженной в ui-view страницы about. Тем не менее, что я хотел бы сделать, это загрузить страницу about на /about и только страницу us на /us. Возможно ли это?

Ответ 1

Да, это возможно. То, что мы должны использовать, является абсолютным наименованием. Определение состояния будет выглядеть так:

.state('us', {
    url: "/us",
    views : {
      "@" : { // here we are using absolute name targeting
        templateUrl: "views/us.html",
        controller: "UsController", 
      },
    }
    parent: 'about',
    ncyBreadcrumb: {
        label: 'Us'
    }
})

См. документ:

Просмотр имен - Относительные и абсолютные имена

За кулисами каждому представлению присваивается абсолютное имя, которое следует схеме [email protected], где viewname - это имя, используемое в директиве представления, а имя состояния - это абсолютное имя состояния, например. contact.item. Вы также можете написать имена имен в абсолютном синтаксисе.

Например, предыдущий пример также можно было записать как:

.state('report',{
    views: {
      '[email protected]': { },
      '[email protected]': { },
      '[email protected]': { }
    }
})

Как показывает документация, мы можем использовать абсолютное именование. В нашем случае мы будем указывать на корневое состояние, которое nams является пустым (index.html) - часть после разделителя @. И это неназванный вид - строка Пусто перед @. Вот почему мы используем:

    views : {
      "@" : {

ПРИМЕЧАНИЕ: за кулисами UI-Router используется для состояния us:

    views : {
      "@about" : {

Существует рабочий плункер, с этими состояниями в действии:

// States
$stateProvider

  .state('index', {
    url: "/index",
    templateUrl: 'tpl.html',
  })
  .state('about', {
    url: "/about",
    templateUrl: 'tpl.html',
  })
  .state('us', {
    url: "/us",
    parent: "about",
    views : {
      '@': {
        templateUrl: 'tpl.html',
      },
    }
  })

Проверьте действие, что если "us" - это имя состояния, ui-sref = "us" будет правильно перемещаться к '/about/us'.

Ответ 2

Конечно, только потому, что государство разделяет часть URL-адреса, это не значит, что это должно быть отношение родитель/ребенок. Просто установите URL-адрес состояния us на /about/us и не дайте ему родителя.

App.config(function($stateProvider, $urlRouterProvider) {
    //
    //
    // Now set up the states
    $stateProvider
    .state('index', {
        url: "/index",
        templateUrl: "views/home.html",
        controller: "MainController",
        ncyBreadcrumb: {
            label: 'Home'
        }
    })
    .state('About', {
        url: "/about",
        templateUrl: "views/about.html",
        controller: "AboutController",
        ncyBreadcrumb: {
            label: 'About',
            parent: 'index'
        }
    })
    .state('us', {
        url: "/about/us",
        templateUrl: "views/us.html",
        controller: "UsController",
        ncyBreadcrumb: {
            label: 'Us'
        }
    })
    //
    // For any unmatched url, redirect to /home
    $urlRouterProvider.otherwise("/index");
});