【问题标题】:AngularJS - "Error: Template must have exactly one root element" when using Angular-UI TypeaheadAngularJS - 使用Angular-UI Typeahead时“错误:模板必须只有一个根元素”
【发布时间】:2013-07-12 20:45:30
【问题描述】:

我在我的应用程序的“索引”页面上使用AngularUI Typeahead。我没有做任何花哨的事情 - 事实上,我只是想让他们在他们的 UI 网站上建立的示例正常工作,我收到了这个错误:

Error: Template must have exactly one root element

我不知道这是什么意思,但只有当我有以下代码时才会发生:

<input type="text" ng-model="selected" typeahead="state for state in states | filter:$viewValue">

如果相关,我的主页控制器(通过 $routeProvider 调用 / 索引目录):

function indexCtrl($scope, $location, $resource) {
  $scope.selected = undefined;
  $scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];

}

请注意,页面上的其他控制器工作正常,只是 $scope.selected/$scope.states 引起了麻烦。我无法弄清楚错误的含义,因此故障排除非常困难!

有什么想法吗?

编辑这是我的 HTML 模板:

    <html ng-app="myApp" class="ng-scope">
    <head>
    // Head stuff, probably irrelevant
    </head>
    <body>
    <div class="container">
        <div ng-view="" class="row-fluid">
            <form class="row-fluid">
                <div class="container-fluid">
                    <input type="text" ng-model="selected" typeahead="state for state in states | filter:$viewValue">
                </div>
            </form>
        </div>
    </div>
// A bunch of Angular scripts are here
    </body>
    </html>

这绝对与 typeahead 脚本有关,我可以删除 typeahead="state for state in states | filter:$viewValue" 并且脚本可以工作(尽管显然 typeahead 函数不...)

【问题讨论】:

  • input(type="text", ng-model="selected", typeahead="state for state in states | filter:$viewValue")是什么,不是&lt;input type="text" ...&gt;吗?
  • @YeLiu 哦,抱歉,这是 ExpressJS 使用的 Jade 模板引擎的一部分。它就像你说的那样呈现,我会更新问题以反映这一点。
  • 发布您的 html/模板,因为错误与模板有关。
  • @YeLiu 我不明白在这种情况下“根元素”是什么意思。编辑以包含我的模板。

标签: javascript angularjs angular-ui angular-ui-bootstrap


【解决方案1】:

我有同样的问题,但使用 ui-select 指令但一般问题是相同的。

我终于可以解决我的问题,并且我可以确定,在我的情况下,问题在于我添加了一个 http 拦截器来自动将令牌添加到所有 http 请求回服务器。

但由于令牌是在内部进程检查模板缓存之前添加的,所以最终请求的文件 (bootstrap.select.tpl.html) 已被我的拦截器 (bootstrap.select.tpl.html? token=xxxxxx) 并且它在缓存的哈希中不再是已知的,服务器喜欢从服务器下载它。但在服务器上,我无法解析 url 请求,我用默认网页回答。

我确实修改了我的拦截器以检查请求的 url 是否已经在缓存中,并且只有在缓存中找不到页面时才添加令牌。之后一切正常。

希望有人能从这样的解决方案中受益

/**
 * Intercept all http-Traffic to add the token
 */
app.config(
  function ($httpProvider) {
    $httpProvider.interceptors.push(function ($q, $rootScope, $localStore, $templateCache) {
        return {
          request: function (config) {
            // check if the cache has the file already loaded, in this case do not append any token
            if (!$templateCache.get(config.url)) {
              if (!config.params) config.params = {};
              var token = $rootScope.token;
              if (token !== null && token !== undefined && token !== 'undefined') {
                $localStore.set('token', token);
                // only if it's a valid token, add it
                config.params.token = token;
              }
            }
            return config || $q.when(config);
          }
        };
      }
    );
  }
);

【讨论】:

  • 在我的情况下它是 angular-cache-buster。
【解决方案2】:

遇到 sam 问题,发现了我的 bug。 我有removeAll的templateCache,那会导致所有的模板都不行

【讨论】:

    【解决方案3】:

    您还需要将模板文件包装在一个元素中(包括 cmets)。阅读更多here

    【讨论】:

      【解决方案4】:

      确保您添加了正确的ui-bootstrap-tpls-[version].min.js 文件(tpls 版本包含模板和代码)。您将需要一个引用本地或 cdn 版本的脚本标记。

      这个错误很可能是由于 Angular 无法找到模板来显示预输入选项,尝试通过 http 获取一个并检索 404 代替(使用新的根 html 元素,因此错误) .

      【讨论】:

      • 并确保将 'ui.bootstrap.tpls' 作为 Angular 模块的一部分!
      • 还要在ui-bootstrap-tpls.js标签之前包含angular-bootstrap.js脚本标签
      • 我认为“ui.bootstrap”暗示了这些依赖关系,但显然我错了。感谢您为我省去了几个小时的麻烦!
      【解决方案5】:

      您的 indexCtrl 未在您的 html (ng-controller) 中引用。您不应该使用 undefined use $scope.selected = ''; 来初始化您选择的变量,或者干脆将其删除。 此代码有效:

      <div class="container">
          <div ng-controller="mainCtrl" class="row-fluid">
              <form class="row-fluid">
                  <div class="container-fluid">
                      <input type="text" ng-model="selected" typeahead="state for state in states | filter:$viewValue">
                  </div>
              </form>
          </div>
      </div>
      
      angular.module('myApp', ['ui.bootstrap'])
          .controller("mainCtrl", function ($scope) {
          $scope.selected = '';
          $scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];
      });
      

      JSFiddle:http://jsfiddle.net/alfrescian/EDZgT/

      【讨论】:

        猜你喜欢
        • 2017-02-02
        • 1970-01-01
        • 2018-09-09
        • 1970-01-01
        • 2015-03-15
        • 2016-09-07
        • 2017-03-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多