AngularUI路由器:使用相同url模式的多个状态

AngularUI Router: multiple states with same url pattern

本文关键字:模式 状态 url 路由器 AngularUI      更新时间:2023-09-26

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

假设同一个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})

关于嵌套状态和通用控制器的另一个可能的解决方案,请参阅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(例如,如果它们具有完全独立的控制器等),则此解决方案更好


也可以在StackOverflow上看到关于类似问题的另一个问题

这在AngularJS中非常有用

可以为相同url模式的多个状态指定动态路由

My Code is As follow

模块初始化,

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

也许这对你有帮助…享受…

您需要使用嵌套状态

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

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

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

  • /:post -用于简单视图
  • /:post/advanced -用于高级视图

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

另一个选项是添加url参数,例如:
  • /:post -用于简单视图
  • /:帖子?先进观点=

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