使用ng-include重用以前实例化的模板

时间:2015-02-22 03:12:14

标签: javascript angularjs angularjs-ng-include

我需要在表单上使用<select>来控制剩余的可用输入。通过将<select>绑定到ng-include的src,可以轻松实现这一点。

问题是每次用户更改所选值(以及src模板)时,angular会从头开始编译模板并附加新范围。这具有每次擦除所有输入数据的效果。用户希望如果他们更改回先前选择的选项,他们之前输入的所有字段数据仍将存在。

有没有内置的方法来实现所需的行为?理想情况下是一个选项,以便ng-include将重用以前编译的模板和相关范围?

一种解决方法是ng-include所有模板,并使用ng-show仅显示当前模板。这看起来很重,但页面上有很多DOM元素。 (特别是对于我的用例,大约有20个不同的模板,整个<select>元素和动态模板控件可以在一个页面上重复多达40次。)

这是jsFiddle。期望的结果是模板1上的计数器在将下拉菜单更改为模板2并返回到1时保持不变。

1 个答案:

答案 0 :(得分:1)

我觉得这个问题很有意思。如果没有将模型放入服务中(这可能是正确的方法),我认为没有使用ng-include缓存模板的内置方法,而不使用ng-repeat,如in this fiddle所示。< / p>

<div ng-controller="Ctrl">
    <select ng-model="template" ng-options="t.name for t in templates">
     <option value="">(blank)</option>
    </select>
    url of the template: <tt>{{template.url}}</tt>
    <hr/>
    <div ng-repeat="t in templates" ng-include="t.url" ng-show="template.name == t.name">
     </div>
  </div>

正如您所指出的,此解决方案的缺点是您最终会在DOM中使用大量元素。

为了好玩,我写了一个ng-include版本来缓存模板元素并重用它。在最坏的情况下,您最终可能会创建尽可能多的DOM节点,但由于它们仅按需创建,并且由于在任何给定时间只有一个在DOM中,因此从角度角度来看它应该保持相当高效。

Here is the fiddle for this directive

.directive('cacheInclude', function ($compile, $http, $templateCache) {
    return {
        link: function (scope, element, attrs, ctrl) {
            var cache = {};
            var currentElement = element;
            var replaceCurrent = function(cacheEntry) {

                currentElement.replaceWith(cacheEntry);
                currentElement = cacheEntry;
            };
            scope.$watch(function(){
                return scope.$eval(attrs.src);
            }, function () {
                var src = scope.$eval(attrs.src);

                if (!cache[src]) {
                    $http.get(src, {cache: $templateCache}).then(function (result) {


                        cache[src] = $compile(result.data.trim())(scope.$new());
                        replaceCurrent(cache[src]);
                    });
                } else {

                    replaceCurrent(cache[src]);
                }
            });
        }
    }
})

它不是“内置”,但我认为这是一个很好的中间解决方案。注意,该指令“仅作为示例”,仍然需要错误处理等。