Angular маршрутизация ui-view внутри другого ui-view

Обзор концепции:

У нас есть две вкладки для индекса html. Там мы маршрутизируем эти вкладки следующим образом:

<div ui-view></div>

На второй вкладке есть селектор, который переключает содержимое вкладки в другое ui-представление, подобное этому:

<div ui-view="{{vm.currentView}}"></div>

где vm.currentView - это имя состояния маршрутизации ( "book1" и т.д.).

 .state('tab2', {
        abstract: true,
        templateUrl: 'tab2.html',
        controller: 'Tab2Controller',
        controllerAs: 'vm'
    })
    .state('tab2.content', {
        url: '/tab2',
        views: {
            '': {
                templateUrl: 'tab2.html'
            },
            '[email protected]': {
                templateUrl: 'tab2-book1.html'
            },
            '[email protected]': {
                templateUrl: 'tab2-book2.html'
            },
            '[email protected]': {
                templateUrl: 'tab2-book3.html'
            },
            '[email protected]': {
                templateUrl: 'tab2-book4.html'
            }
        }
    });

Все в порядке, кроме одного: содержимое данных и имя представления изменяются, но содержимое шаблона не является.

Я решил это другим способом (основанным на исключении концепции ui-view внутри другой ui-view и отдельных представлений в состояниях). Но я все еще хочу знать: "Как это сделать, используя концепцию ui-view внутри ui-view?"

Здесь пример Plunker

Ответ 1

Его можно сделать "ui-view внутри другого ui-view".

Предположим, что у вас есть index.html

<div ui-view="content"></div>

и поставщик состояния - это: -

$stateProvider
   .state('books', {
        parent: 'pages',
        url: '/books',                   
        views: {
            '[email protected]': {
                 templateUrl: 'books.html',
                 controller: 'BooksController'
             }
        }
   })

В books.html у вас есть ссылки и другой ui-view (вложенный ui-view). На клике ссылок заполняется вложенный вид ui.

books.html

<div>
     <a ui-sref="book1"></a>
     <a ui-sref="book2"></a>
     <a ui-sref="book3"></a>
</div>
<!-- nested ui-view -->
<div ui-view="bookDetails"></div>

теперь поставщик состояния: -

 $stateProvider
    .state('books', {
        parent: 'pages',
        url: '/books',                   
        views: {
            '[email protected]': {
                 templateUrl: 'books.html',
                 controller: 'BooksController'
             }
        }
    })
    .state('book1', {
        parent: 'books',                  
        views: {
            '[email protected]': {
                 templateUrl: 'book1.html',
                 controller: 'BookOneController'
             }
        }
    })
    .state('book2', {
        parent: 'books',                 
        views: {
            '[email protected]': {
                 templateUrl: 'book2.html',
                 controller: 'BookTwoController'
             }
        }
    })
    .state('book3', {
        parent: 'books',                
        views: {
            '[email protected]': {
                 templateUrl: 'book3.html',
                 controller: 'BookThreeController'
             }
        }
    })

bookDetails @books: - заполнить "bookDetails" ui-view в "книжном" состоянии или мы можем сказать, что находим "bookDetails" ui-view внутри "книги" и заполняем его "просмотрами" '.

Ответ 2

Как я уже объяснял ранее, я просто хочу сделать "ui-view внутри другого ui-view", но это кажется невозможным. Я нашел два способа решить эту "ошибку" (?).

Первый способ: Исключить 'ui-view внутри другого ui-view' и использовать 'ng-include'

Простейший вариант с минимальным изменением кода. Как вы видите здесь, я заменил

 <div ui-view="{{vm.currentView}}"></div>

с

 <ng-include src="vm.getTemplateUrl(vm.selectedBook.id)"/>

и добавить функцию к контроллеру, то есть шаблоны переключателей:

function getTemplateUrl(id) {
            switch (id) {
                case 0:
                    return 'tab2-book1.html';
                case 1:
                    return 'tab2-book2.html';
                case 2:
                    return 'tab2-book3.html';
                case 3:
                    return 'tab2-book4.html';
                default:
                    return 'tab2-book4.html';
            }
        }

Второй способ: формально сохранить 'ui-view внутри другого ui-view' и отдельные представления по состояниям

И как вы видите здесь, формально я сохраняю 'ui-view внутри ui-view', но на самом деле я просто полностью заменяю сингл ui -view по шаблону из другого единственного ui-view (не может установить второй ui-view по имени).

$urlRouterProvider
        .when('/tab2', '/tab2/book4');

    $stateProvider
        .state('tab2', {
            url: '/tab2',
            templateUrl: 'tab2.html'
        })
        .state('tab2.book1', {
            url: '/book1',
            params: {
                id: 0
            },
            templateUrl: 'tab2-book1.html',
            controller: 'Tab2Controller',
            controllerAs: 'vm'
        })
        .state('tab2.book2', {
            url: '/book2',
            params: {
                id: 1
            },
            templateUrl: 'tab2-book2.html',
            controller: 'Tab2Controller',
            controllerAs: 'vm'
        })
        .state('tab2.book3', {
            url: '/book3',
            params: {
                id: 2
            },
            templateUrl: 'tab2-book3.html',
            controller: 'Tab2Controller',
            controllerAs: 'vm'
        })
        .state('tab2.book4', {
            url: '/book4',
            params: {
                id: 3
            },
            templateUrl: 'tab2-book4.html',
            controller: 'Tab2Controller',
            controllerAs: 'vm'
        });

Где содержимое tab2.html:

<ui-view class="page-container"></ui-view>

При изменении селектора я вызываю vm.changeHandbook(vm.selectedBook) для переключения шаблонов:

function changeHandbook(ref) {
            $state.go(ref.value);
        }

Это самый странный и трудный путь, но в итоге мы получаем более чистый код.