【问题标题】:Angular UI-router and using dynamic templatesAngular UI-router 和使用动态模板
【发布时间】:2014-11-12 14:09:54
【问题描述】:

我正在尝试使用 rootscope 值加载模板文件作为其名称。 我有一个初始化控制器,它将 $rootScope.template 设置为“whatever.html”,然后我的路由如下:

$stateProvider.state('/', {
  url: '/',
  access: 'public',
  views: {
    page: {
      controller: 'HomeCtrl',
      templateProvider: function($templateFactory, $rootScope) {
        return $templateFactory.fromUrl('/templates/' + $rootScope.template);
      }
    }
  }
});

但这不起作用。它实际上冻结了整个 chrome,因此我必须终止进程才能停止它......我也用 templateUrl 尝试过,但没有结果。

那么我如何将我的动态模板文件与 UI-router 一起使用?

【问题讨论】:

  • 你能创建一个 plunkr.co 来在上下文中显示这个失败吗?
  • templateProviders 似乎还可以。我为此创建了一个 plunker:plnkr.co/edit/x8tsIBkKHM1cxfstyESt?p=preview 所以,问题可能不在这里。
  • 是的,似乎工作正常。我的问题是/是这个 $rootscope 值是来自数据库的查询值。现在一切正常,如果我手动声明 $rootScope.template 但查询花费的时间太长(或者我真的不知道问题是什么),因此在 templateProvider 需要它的时候还没有准备好。
  • 任何想法如何获取我的模板名称并在我的路由器中使用它?像上面的问题一样,但不是 $rootScope.template = "whatever.html" 而是一个查询值?

标签: angularjs angular-ui-router


【解决方案1】:

类似于你的其他问题(按我找到它们的顺序)Angular and UI-Router, how to set a dynamic templateUrl,我也创建了a working plunker to show how to。它是如何工作的?

所以,如果这是状态调用:

<a href="#/parent/child/1">#/parent/child/1</a>
<a href="#/parent/child/2">#/parent/child/2</a>

这些将是状态:

  $stateProvider
    .state('parent', {
      url: '/parent',
      //abstract: true,
      templateUrl: 'views.parentview.html',
      controller: function($scope) {},
    });

  $stateProvider
    .state('parent.child', {
      url: '/child/:someSwitch',
      views: {
         // see more below

那么我们就可以使用这个templateProviderdefiniton:

templateProvider: function($http, $stateParams, GetName) {

    // async service to get template name from DB
    return GetName
        .get($stateParams.someSwitch)
        // now we have a name
        .then(function(obj){
           return $http
              // let's ask for a template
              .get(obj.templateName)
              .then(function(tpl){
                  // haleluja... return template
                  return tpl.data;
           });      
        })

}, 

我们可以看到异步结果的链接:

// first return of promise
return asyncstuff
  .then(function(x){
    // second return of a promise once done first
    return asyncstuff
      .then(function(y){  
       // again  
        return asyncstuff
          .then(function(z){
            return ... it
          }
      }

  }

这就是神奇的templateProvider 可以为我们做的事情......等到所有的承诺都得到解决,然后使用已知的模板名称甚至其内容继续执行。检查示例here。更多关于模板提供者:Angular UI Router: decide child state template on the basis of parent resolved object

【讨论】:

  • 这看起来很有希望,但我想问一下,$http 服务真的需要获取模板吗? (这是我通过查看您的 plunker 示例所理解的),工厂 GetName#get 确实已经返回了模板名称,所以......您的 plunker 的第 29 行上的 $http 调用是所有这些工作所必需的吗?为什么?谢谢!
  • @Jose 如果我确实理解您的问题,我宁愿使用讨论过的 $templateRequest,例如herethere
  • 酷,现在看看你的建议。但是,为了争论,您认为您可以回答我的问题吗? templateProvider 是否确实需要对 $http 进行 final 调用来获取模板?感谢您的友好回复。
  • @Jose,抱歉没有那么多时间.. 但我想是的。 GetName 只是获取名称,而 $http 获取它的内容。 templateProvider 必须返回模板!所以,它必须调用 $http 来获取它。希望它有所帮助..也许会提出新的问题,大量的观众可以给你更好的方向..
  • 没关系!现在已经足够好了。我们程序员总是很忙!你的建议看起来更好。读起来!祝你有美好的一天。