AngularJS - UI 路由器 - 以编程方式添加状态

IT技术 javascript angularjs angular-ui-router angular-services
2021-01-31 07:25:32

有没有办法在module配置后以编程方式向 $stateProvider 添加状态,例如 service ?

为了给这个问题添加更多上下文,我有一种情况,我可以采用两种方法:

  1. 尝试强制重新加载module配置中定义的状态,问题是状态的reloadOnSearch设置为false,所以当我尝试$state.go('state.name', {new:param}, {reload:真的}); 没有任何react,有什么想法吗?

状态定义

.state('index.resource.view', {
  url: "/:resourceName/view?pageNumber&pageSize&orderBy&search",
  templateUrl: "/resourceAdministration/views/view.html",
  controller: "resourceViewCtrl",
  reloadOnSearch: false,
})
  1. 尝试以编程方式添加我需要从服务加载的状态,以便路由可以正常工作。如果可能的话,我宁愿选择第一个选项。
3个回答

有关更新的信息,请参阅 -edit-

通常状态会$stateProvider在配置阶段添加到如果要在运行时添加状态,则需要保留对$stateProvider周围的引用

这段代码未经测试,但应该做你想做的。它创建了一个名为runtimeStates. 您可以将其注入运行时代码,然后添加状态。

// config-time dependencies can be injected here at .provider() declaration
myapp.provider('runtimeStates', function runtimeStates($stateProvider) {
  // runtime dependencies for the service can be injected here, at the provider.$get() function.
  this.$get = function($q, $timeout, $state) { // for example
    return { 
      addState: function(name, state) { 
        $stateProvider.state(name, state);
      }
    }
  }
});

我已经UI-Router Extras实现了一些称为Future States 的东西,它们为您处理了一些极端情况,例如将 url 映射到尚不存在的状态。Future States 还展示了如何延迟加载运行时状态的源代码。查看源代码以了解所涉及的内容。

-edit- 用于 UI-Router 1.0+

在 UI-Router 1.0 中,可以在运行时使用StateRegistry.register注册和取消注册状态StateRegistry.deregister

要访问 StateRegistry,请将其注入为$stateRegistry,或$uiRouter通过注入并访问它UIRouter.stateRegistry

UI-Router 1.0 还包括开箱即用的未来状态,它处理状态定义的延迟加载,甚至通过 URL 同步。

@ChrisT 现在我对延迟加载状态的直接 url 访问有问题,有没有办法使用 $stateNotFound 或其他一些事件在 404 重定向之前从服务加载状态?
2021-03-19 07:25:32
@ChrisT 是否可以以编程方式删除状态?
2021-03-20 07:25:32
@ChadRobinson 也为您 +1
2021-03-24 07:25:32
我测试了这个解决方案,它工作得很好,我确实有小问题,因为我使用了“index.resource.DYNAMIC-STATE-NAME.view”,它正在排队动态状态,可能是因为它被识别为父状态,一旦我改变'index.resource.DYNAMIC-STATE-NAMEView'的状态名称它工作正常。
2021-04-09 07:25:32
感谢未来国家的贡献,克里斯!由于它的value,我对这个问题投了赞成票,但将我的另一个答案留在下面,因为那篇博文也有一些有趣的花絮。
2021-04-11 07:25:32

克里斯 T 搞定了!提供者是要走的路。您不必将其贴在窗口对象、保护程序、更多保护等上。

用这篇文章交叉引用他的回答真的很有帮助:http : //blog.xebia.com/2013/09/01/differences-between-providers-in-angularjs/#provider

该解决方案使在配置块期间的特定module $stateProvider 可在其他module的运行块期间访问。

在我的情况下,我根据用户的权限动态生成仪表板状态。

在我的配置块期间,我的提供者被设置,传递module的 stateProvider(稍后访问)。

//in dashboard.module.js

var dashboardModule = angular.module('app.modules.dashboard',[
        'app.modules.dashboard.controllers',
        'app.modules.dashboard.services',
        'app.modules.dashboard.presentations.mileage'
    ])

    .provider('$dashboardState', function($stateProvider){
        this.$get = function(PATHS, $state){
            return {
                addState: function(title, controllerAs, templatePrefix) {
                    $stateProvider.state('dashboard.' + title, {
                        url: '/' + title,
                        views: {
                            'dashboardModule@dashboard': {
                                templateUrl: PATHS.DASHBOARD + (templatePrefix ? templatePrefix + '/' : '/') + title + '/' + title + '.view.html',
                                controller: controllerAs ? controllerAs : null
                            }
                        }
                    });
                }
            }
        }
    });

这将使我的仪表板状态提供程序可用于其他module,而不是将其拍打在窗口上。

然后在我的用户module的运行块(控制器)中,我可以访问仪表板的状态提供程序并动态注入状态。

var UserControllers = angular.module('app.modules.user.controllers', [])

.controller("UserLoginController", ["$state", "$dashboardState", function($state, $dashboardState){

    $dashboardState.addState('faq', null, 'content');

    $state.go('dashboard.faq');

}]);

嗨,我尝试实现这个,但我收到一条错误消息,提示未知提供者。如何在 config.js 中注册提供程序?我想将提供者注入控制器。
2021-04-05 07:25:32
我试过这种方法,但在刷新时它不起作用。这不仅仅是时间问题。我收到了大量的摘要错误
2021-04-07 07:25:32
到目前为止最简单的方法,不需要 AMD(如 Ui-Router Extras)。只需要确保在新module中添加提供程序,否则将无法工作。
2021-04-11 07:25:32

是的,可以这样做,但是因为涉及缓存层,所以很复杂。Alex Feinberg 在他的博客上记录了一个解决方案:

http://alexfeinberg.wordpress.com/2014/03/08/dynamically-populating-angular-ui-router-states-from-a-service/

文章最后包含了一个使用 stateProvider 创建状态的例子:

app.stateProvider.state(ent.lob.name.toLowerCase(), {
    url: '/' + ent.lob.name.toLowerCase(),
    controller: ent.lob.name.toLowerCase() + 'Controller',
    templateUrl: 'lobs/views/' + ent.lob.name.toLowerCase() + '.html'
});
文章中很少有重点,但对我来说,用stateProvider扩展 app 对象有点奇怪谢谢
2021-04-06 07:25:32