javascript AngularJS - 使用 Angular-UI Typeahead 时出现“错误:模板必须只有一个根元素”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17646573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 09:04:05  来源:igfitidea点击:

AngularJS - "Error: Template must have exactly one root element" when using Angular-UI Typeahead

javascriptangularjsangular-uiangular-ui-bootstrap

提问by JVG

I'm using AngularUI Typeahead, on the 'index' page of my app. I'm not doing anything fancy - in fact, I'm just trying to get the example they've got up on their UI site working, and I'm getting this error:

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

Error: Template must have exactly one root element

I have no idea what this means, but it only happens when I have the following code:

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

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

If relevant, my controller for my main page (which is called via $routeProviderfor /index directory):

如果相关的,我的控制器,我的主要页面(这是通过所谓$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'];

}

Note that the rest of the controller on the page works absolutely fine, it's just the $scope.selected/$scope.statesthat is causing trouble. I can't figure out what the error means, so troubleshooting is quite difficult!

请注意,页面上控制器的其余部分工作得非常好,只是$scope.selected/$scope.states造成问题的原因。我无法弄清楚错误意味着什么,因此故障排除非常困难!

Any ideas?

有任何想法吗?

EDITHere is my HTML template:

编辑这是我的 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>

It's definitely related ot the typeaheadscript, I can remove typeahead="state for state in states | filter:$viewValue"and the script works (although obviously the typeaheadfunction doesn't...)

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

回答by AndrewD

Make sure you are adding the correct ui-bootstrap-tpls-[version].min.jsfile (tpls versions contain templates as well as code). You will need a script tag somewhere referencing a local or cdn version.

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

It is most likely that this error is caused by angular not being able to find the template to display the typeahead options, attempting to fetch one over http and retrieving a 404 instead (with a new root html element, thus the error).

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

回答by dide

I had the same problem, but with the ui-select directive but the general problem would be the same.

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

I could finally solve my problem and I could identify that in my case the problem was that I had added a http interceptor to add automatic to all http request the token back to the server.

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

But as the token was added before the internal process could check for the template cache it was ending up that the requested file (bootstrap.select.tpl.html) was changed by my interceptor (bootstrap.select.tpl.html?token=xxxxxx) and it was no longer known in the hach of the cache and the server like to download it from the server. But on the server I could not resolve the url request and I answer with the default webpage.

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

I did modify my interceptor to check if the requested url is not already in the cache and only add the token if the page was not found in the cache. After that everything was running fine.

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

Hope somebody can benefit from such solution

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

/**
 * 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);
          }
        };
      }
    );
  }
);

回答by alfrescian

your indexCtrlis not referenced in your html (ng-controller). You shouldn't init your selected variable with undefined use $scope.selected = '';instead or simply remove it. This code is working:

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/

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

回答by Rafael

also you need to wrap your template file in one element ( including comments). read more here

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

回答by ElvisMcak

meet the sam problem, and found my bug. I have removeAll the templateCache, that will lead all the template does't work

遇到山姆问题,发现了我的错误。我已经删除了所有的模板缓存,那会导致所有的模板都不起作用