Angular UI Router:具有相同url模式的多个状态

时间:2014-06-11 16:00:37

标签: javascript angularjs angular-ui-router

嘿嘿所有我遇到了我认为常见的路由问题,但我无法找到解决方案。基本上我的页面有两种状态,基本和高级,我希望两种状态的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模式,但只使用基于当前状态的不同模板?

4 个答案:

答案 0 :(得分:19)

假设您不能拥有两个具有相同网址的州,为什么不同时将两个州合并为一个? 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})

对于具有嵌套状态和公共控制器的另一种可能解决方案,请参阅ui-router的github页面上的问题#217#1096

在那里提出的解决方案创建了第三个状态,其控制器执行调度工作,而您想要登陆的两个状态(basicadvanced)具有空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不同(例如,如果他们有完全独立的控制器等),则此解决方案会更好。

另见another question on StackOverflow about a similar issue

答案 1 :(得分:1)

这在 AngularJS

中非常有用

您可以指定具有相同网址格式的多个状态的动态路由

我的代码如下,对您有用,

模块初始化,

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");

这可能对你有帮助... 享受...

答案 2 :(得分:-1)

您需要使用嵌套状态

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)
}

答案 3 :(得分:-1)

为什么要在同一个网址上映射两个不同的视图?当用户想要在其中一个状态上添加书签时,您是否想过这个问题?如果他们有完全相同的网址,您怎么知道哪一个?

我建议定义两个不同的状态,如:

  • /:post - for the simple view
  • /:post / advanced - 用于高级视图

这可以通过将/:post定义为抽象状态和简单和高级视图的两个不同状态来完成。为方便起见,简单视图将作为默认值。如果您喜欢这个想法,我可以为您提供一个示例解决方案。

另一个选项是添加url参数,例如:

  • /:post - for the simple view
  • /?:交视图=先进

我希望这个答案会对你有所帮助。至少从不同角度看问题;)。