Вложенные представления внутри модального не отображаются. (ui-маршрутизатор и ui-bootstrap)


У меня возникли проблемы с созданием модала, который реагирует на состояние приложения. Из angular ui-router wiki я увидел, как достичь своей цели, но мой код не работает, и я не понимаю, почему по следующим причинам:

  1. когда маршрутизатор приложения / sign/in модальный запускается
  2. Я вижу следующий вывод на моей консоли

    => "about.sign"

    => "about.sign.in"

  3. 2) означает, что и маршрутизаторы, и стрельба! Другими словами модальный должен быть открыт about.sign и шаблон из состояния about.sign.in должен быть вставлен в его Родительский шаблон, точнее в тег.

Я испробовал оба метода. Именованные ui-представления и анонимные, но ни один не работал.

Https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-open-a-dialogmodal-at-a-certain-state

 var app = angular.module('app.auth',
    [
      'ui.bootstrap',
      'ui.router'
    ]);

  app.config(function($stateProvider){
    $stateProvider
      .state('about',{
        url: '/',
        views:{
          'main': {
            templateUrl: 'about/about.tpl.html'
          }
        }
      })
      .state('about.sign',{
        url: '',
        onEnter: function($stateParams, $state, $modal){
          console.log('about.sign')
          var modalInstance = $modal.open({
            template:'<h1>Modal</h1><div ui-view="bar-view"></div>',
            size: 'sm',
          });
        }
      })
      .state('about.sign.in',{
        url:'sign/in',
        onEnter: function($stateParams, $state, $modal){
          console.log('about.sign.in')
        },
        views: {
          'bar-view': {
            template: 'Sign in #1'
          }
        }

      })
      .state('about.sign.up',{
        url:'sign/up',
        onEnter: function($stateParams, $state, $modal){
          console.log('about.sign.in')
        },
        views: {
          'bar-view': {
            template: 'Sign up #2'
          }
        }

      })
  }); //end of app.config

Я делаю что-то не так с этими вложенными представлениями??

2 3

2 ответа:

Я столкнулся и с этим. Оказывается, вам нужно использовать "родитель" вместо точечной нотации.

Здесь находится плунжер

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

    $urlRouterProvider.otherwise('/');

    $stateProvider
      .state('view', {
        url: '',
        template: '<button class="btn btn-default" ui-sref="modal"> Modal</button> <ui-view />',
        controller: function($scope) {
        }
      })
      .state('modal', {
        //abstract: true,
        parent: 'view',
        url: '/modal',
        onEnter: ['$modal', '$state', function($modal, $state) {
            console.log('Open modal');
            $modal.open({
              template: '<button class="btn btn-danger" ui-sref="signin"> sign-in </button> <button ui-sref="signout" class="btn btn-success"> sign-out </button> <div ui-view="modal"></div>',
              backdrop: false,
              windowClass: 'right fade'
            }).result.finally(function() {
              $state.go('list');
          });
        }]
      })
      .state('signin', {
        url: '/signin',
        parent: 'modal',
        views: {
          'modal@': {
            template: '<p>sign-in</p>'
            }
          }
      })
      .state('signout', {
        url: '/signout',
        parent: 'modal',
        views: {
          'modal@': {
            template: '<p>sign-out</p>'
            }
          }
      })
    }]);

Я думаю, что принятый ответ является хорошим. (Трюк состоял в том, чтобы называть представление modal@ вместо просто modal - см. docs для объяснения.) Но я подумал, что напишу более общее решение, на случай, если это поможет другим, кто приходит сюда с похожими проблемами. (Мне потребовалось довольно много времени, чтобы понять все это.)

Одно заметное отличие от моего подхода заключается в том, что я решил создать контроллер для запуска модального, а не использовать крюк onEnter (хотя все остальные примеры, которые я видел, использовали onEnter), потому что onEnter не дает вам доступа к области. Таким образом, контроллеры как для модальных, так и для дочерних состояний могут наследовать одну и ту же родительскую область.

Интересная оговорка: именованные представления для дочерних состоянийне могут ссылаться на родительское состояние. Модальный по существу создает свое собственное состояние, поэтому в моем примере ui-view="modal" не существует в контексте состояния launch_modal - он существует в корневом неназванном шаблоне (следовательно, почему взгляд ребенка должен быть modal@, а не modal@launch_modal).

registerRoutes: function($stateProvider) {
  var modal_instance = null;
  return $stateProvider.state('launch_modal', {
    url: '/',
    template: '',
    controller: [
      '$uibModal', '$state', '$scope', function($modal, $state, $scope) {
        // init scope variables that you want the modal and child states to inherit
        $scope.modal = {
          title: '',
        };

        // launch the dialog
        modal_instance = $modal.open({
          template: '<div ui-view="modal">',
          controller: 'MyModule.Controllers.DialogController',
          scope: $scope
        });

        // make sure we leave the state when the dialog closes
        return modal_instance.result['finally'](function() {
          modal_instance = null;
          if ($state.includes('launch_modal')) {
            return $state.go('^');
          }
        });
      }
    ],
    onExit: function() {
      // make sure the dialog is closed when we leave the state
      if (modal_instance != null) {
        modal_instance.close();
      }
    }
  }).state('launch_modal.child1', {
    url: '',
    views: {
      // note: doing `modal@launch_modal` won't work!
      'modal@': {
        templateUrl: "path/to/child1/template",
        controller: "MyModule.Controllers.Child1ViewController"
      }
    }
  });
}

Надеюсь, что это поможет некоторым людям!