我需要在表单上使用<select>
来控制剩余的可用输入。通过将<select>
绑定到ng-include
的src,可以轻松实现这一点。
问题是每次用户更改所选值(以及src
模板)时,angular会从头开始编译模板并附加新范围。这具有每次擦除所有输入数据的效果。用户希望如果他们更改回先前选择的选项,他们之前输入的所有字段数据仍将存在。
有没有内置的方法来实现所需的行为?理想情况下是一个选项,以便ng-include
将重用以前编译的模板和相关范围?
一种解决方法是ng-include
所有模板,并使用ng-show
仅显示当前模板。这看起来很重,但页面上有很多DOM元素。 (特别是对于我的用例,大约有20个不同的模板,整个<select>
元素和动态模板控件可以在一个页面上重复多达40次。)
这是jsFiddle。期望的结果是模板1上的计数器在将下拉菜单更改为模板2并返回到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]);
}
});
}
}
})
它不是“内置”,但我认为这是一个很好的中间解决方案。注意,该指令“仅作为示例”,仍然需要错误处理等。