AngularUI Router: несколько состояний с одинаковым шаблоном URL

Привет всем, что я натолкнулся на то, что, как я думал, будет общей проблемой маршрутизации, но я не могу найти решение. В основном моя страница имеет два состояния, базовые и расширенные, и я хочу, чтобы шаблоны URL были одинаковыми для обоих состояний, но загружали только шаблон для текущего состояния (который переводится изнутри контроллера).

config(function ($stateProvider) {

  $stateProvider.state('basic', {
    url: '/:post',
    templateUrl: function (stateParams) {
      return 'post-' + stateParams.post + '-tmpl.html';
    }
  });

  $stateProvider.state('advanced', {
    url: '/:post',
    templateUrl: function (stateParams) {
      return 'post-' + stateParams.post + '-advanced-tmpl.html';
    }
  });
})

controller('myCtrl', function ($state) {
  //
  // In this case, I would expect only the template from
  // the advanced state to load, but both templates are trying
  // to load.
  $state.transitionTo('advanced', {post: 2});
}

Я предполагаю, что переход к совпадающему шаблону загружает заданное состояние, поэтому, когда он совпадает, оба шаблона пытаются загрузить. Есть ли способ выполнить один и тот же шаблон url, но с разными шаблонами, основанными только на текущем состоянии?

Ответы

Ответ 1

Предполагая, что вы не можете иметь два состояния с одним и тем же URL-адресом, почему бы вам не пойти и объединить два состояния в один? Ui-router уже позволяет вам иметь настраиваемую функцию для возврата шаблона. Вам просто нужно добавить еще один скрытый настраиваемый параметр (позвоните ему advanced) в декларацию состояния:

$stateProvider.state('basicOrAdvanced', {
  url: '/:post',
  templateUrl: function (stateParams) {
    if (stateParams.advanced) {
      return 'post-' + stateParams.post + '-advanced-tmpl.html';
    } else {
      return 'post-' + stateParams.post + '-tmpl.html';
    }
  },
  params: {
    advanced: False
  }
});

И затем вы вызываете его с помощью:

$state.transitionTo('basicOrAdvanced', {post: 2, advanced: True})

Для другого возможного решения с вложенными состояниями и общим контроллером см. проблемы # 217 и # 1096 на странице uit-router github.

Представленное там решение создает третье состояние, контроллер которого выполняет диспетчерскую работу, тогда как два состояния, в которые вы хотите приземлиться (basic и advanced), имеют пустые URL-адреса:

$stateProvider.state('basicOrAdvanced', {
  url: '/:post',
  controller: function($state, $stateParams) {
    if($stateParams.advanced) {
        $state.go('advanced', {post: $stateParams.post});
    } else {
        $state.go('basic', {post: $stateParams.post});
    }
  },
  params: {
    advanced: False
  }
}

Это решение лучше, если ваши состояния отличаются друг от друга по сравнению с простым templateUrl (например, если у них есть полностью отдельные контроллеры и т.д.)


Также см. fooobar.com/questions/195179/....

Ответ 2

Это очень полезно в AngularJS,

Вы можете указать Динамический маршрут для нескольких состояний с одинаковым шаблоном URL

Мой код Как следует, это может быть полезно для вас,

Интеллизация модуля,

var app = angular.module("koops_app", ['ui.router','ui.bootstrap']);    //here you have to define all your required module for your project that you should inject...

Далее

app.config(function ($locationProvider, $httpProvider, $stateProvider, $urlRouterProvider, $wampProvider) {


    // When No Routing i.e Default Routing
    $urlRouterProvider.when('', '/dashboard');


    // 404
    $stateProvider.state("404", {
        url: "/404",
        templateUrl: 'template/404.html',
    });


    // When Only One Argument i.e. Only Module Name
    $stateProvider.state("default", {
        url: "/:section",
        templateUrl: 'views/View-to-be-load.html',  //can use $stateParams.section for dynamic
        reload: true,
        resolve: {
            loadController: ['$q', '$stateParams', '$state',
                        function ($q, $stateParams, $state) {
                            var deferred = $q.defer();
                            deferred.resolve();
                            return deferred.promise;
                        }
                    ]
        },
        controllerProvider: function ($stateParams) {
            return 'controllerName';
        }
    });



        // When Two Argument i.e. Module/Controller
        $stateProvider.state("default/title", {
            url: "/:section/:title",
            templateUrl: 'views/View-to-be-load.html',  //can use $stateParams.section for dynamic
            reload: true,
            resolve: {
                loadController: ['$q', '$stateParams', '$state',
                            function ($q, $stateParams, $state) {
                                var deferred = $q.defer();
                                deferred.resolve();
                                return deferred.promise;
                            }
                        ]
            },
            controllerProvider: function ($stateParams) {
                return 'controllerName';
            }
        });



        // When Three Arguments i.e. Module/Controller/id
        $stateProvider.state("default/title/id", {
            url: "/:section/:title/:id",
            templateUrl: 'views/View-to-be-load.html',  //can use $stateParams.section for dynamic
            reload: true,
            resolve: {
                loadController: ['$q', '$stateParams', '$state',
                            function ($q, $stateParams, $state) {
                                var deferred = $q.defer();
                                deferred.resolve();
                                return deferred.promise;
                            }
                        ]
            },
            controllerProvider: function ($stateParams) {
                return 'controllerName';
            }
    });



        // Otherwise
        $urlRouterProvider.otherwise("/404");

Может быть, это полезно для вас... Наслаждайтесь...

Ответ 3

Вам нужно использовать вложенные состояния

config(function ($stateProvider) {


  $stateProvider.state('post', {
    url: '/:post',
    templateUrl: function (stateParams) {
      return 'post-' + stateParams.post + '-advanced-tmpl.html';
    }
  });

   $stateProvider.state('post.basic', {
    url: '/:post',
    templateUrl: function (stateParams) {
      return 'post-' + stateParams.post + '-tmpl.html';
    }
  });

})

controller('myCtrl', function ($state, $timeout) {
  // go to advanced
  $state.transitionTo('post', {post: 2});
  // after 500ms switch to basic
  $timeout(function() {
      $state.transitionTo('post.basic', {post: 2});
  }, 500)
}

Ответ 4

Почему вы хотите иметь два разных вида, сопоставленных с одним и тем же URL. Представляете ли вы проблему, когда пользователь захочет добавить закладку в одно из состояний? Как бы вы тогда узнали, кто из них, если у них точно такой же URL?

Я бы предложил определить два разных состояния, например:

  • /: post - для простого представления
  • /: post/advanced - для расширенного представления

Это можно сделать с определением /: post как абстрактного состояния и двух разных состояний для простого и расширенного представления. Для удобства простое представление будет действовать как значение по умолчанию. Если вам нравится идея, я могу предоставить вам пример решения.

Другой вариант - добавить параметр url, например:

  • /: post - для простого представления
  • /: запись вид = расширенный

Я надеюсь, что этот ответ поможет вам. По крайней мере, видя вещи с разных сторон;).