【问题标题】:ui-router dynamic template pathui-router 动态模板路径
【发布时间】:2014-05-07 08:09:43
【问题描述】:

我正在使用 ui-router 0.2.8。我想根据设备宽度加载模板。我可以毫无问题地获得设备宽度,将其设置在范围内等,但我可以弄清楚如何将其绑定到 $stateParams。我在另一个控制器中有范围变量,它可以访问状态的控制器,它对状态本身不可用。我已经尝试过 templateProvider 但这只是给我返回一个字符串。我还可以尝试什么才能使其正常工作?

.state('list', {
abstract: true,
url: "/list",
templateUrl: 'views/'+$stateParams.somevalue+'/page.html',
    controller: "myCtrl"
 })
  .state('list.first', {
url: "/first",
templateUrl: "views/first.html"
  })

【问题讨论】:

    标签: angularjs angular-ui-router


    【解决方案1】:

    您可以在$stateChangeStart 事件中访问状态参数。您也可以在那里动态更新templateUrl

    所以你的代码可能看起来像这样:

    angular.module('app', ['ui.router'])
    .run(function($rootScope){
        $rootScope.$on('$stateChangeStart', function(event, toState, toParams) {
            if (toState.name === 'list') {
              toState.templateUrl = 'views/'+toParams.somevalue+'/page.html';
            }
        });
    }
    

    您可能还想看看 ui.router 支持的onEnter callback。我以前没有使用过这个,但它可能比将模板生成代码放入 $stateChangeStart 事件中更简洁。

    【讨论】:

    • 感谢您的回答,效果很好,非常感谢。
    • 这是一个很好的答案,但它打破了 UI-Router 状态配置的想法。不是在一个 Config 块中维护所有状态,而是在多个位置拆分配置,这只会在路上引起头痛。有关更可配置且易于维护的解决方案,请参阅 Dipesh Kc 的答案。
    【解决方案2】:

    您可能正在寻找基于状态参数的动态模板名称

     $stateProvider.state('contacts', {
       templateUrl: function ($stateParams){
         return '/partials/contacts.' + $stateParams.filterBy + '.html';
       }
     })
    

    查看文档了解更多信息 https://github.com/angular-ui/ui-router/wiki#templates

    【讨论】:

    • 真棒答案@Dispesh!
    • 虽然是“正确”的解决方案,但在某些情况下仅使用注入的$stateParams 可能还不够。因此@biofractal 的答案可能是更一般的情况解决方案
    • 是否也可以将 templateUrl 设置为角度指令内的可注入函数?我猜这不是……?
    • 我同意@RicardoPedroni。我不得不使用另一个答案在 toParams 上设置 isMobile 变量,以便该变量可通过 $stateParams 在 templateUrl 函数中使用。这样我就可以为移动设备、桌面设备等提供不同的模板。
    • 这很好,但这里有一个缺点,那就是如果我想在渲染视图之前发出 http 请求,并根据返回的结果,如果我想更改视图该怎么办。我无法在 templateUrl 函数中访问 http
    【解决方案3】:

    这里的这个参考对我了解如何在 Angular 中做动态模板很有帮助,但我想用我自己的解决方案进行更新。

    • 基于 Dipesh Kc 的解决方案 1(这对于为抽象状态重新定义父 templateUrl 非常有效)注意我使用了 toParams 而不是 $stateParams:

      // custom parent template
      .state('template', {
          abstract: true,
          url: "/tm/:tmfolder/:tmview",
          templateUrl: function (toParams) {
              return 'views/' + toParams.tmfolder + '/' + toParams.tmview + '.html';
          },
      })
      .state('template.contacts', {
          url: "/contacts/:folder/:view",
          templateUrl: function (toParams) {
              return 'views/' + toParams.older + '/' + toParams.view + '.html';
          },
      })
      
    • 基于生物分形的解决方案2(无法使用此方法更新父模板Url):

      .state('contact', {
          url: "/contact/:folder/:view"
      })
      
      $rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
          var customStates = ["contact"]
          for (var i = 0; i < customStates.length; i++) {
              if (toState.name.indexOf(customStates[i]) != -1) {
                  toState.templateUrl = 'views/' + toParams.folder + '/' + toParams.view + '.html';
                  break;
              }
          }
      });
      

    【讨论】: