Angularjs 在使用nginclude时避免使用额外的DOM节点
在我从一个简单的HTML演示构建一个有角度的应用程序时,我正在努力思考如何让ng include不使用额外的DOM元素。我正在使用非常纤细的HTML和完全开发的、紧密耦合的CSS(从SASS构建),重构是我想不惜一切代价避免的事情 以下是实际代码:Angularjs 在使用nginclude时避免使用额外的DOM节点,angularjs,angularjs-ng-repeat,angularjs-ng-include,Angularjs,Angularjs Ng Repeat,Angularjs Ng Include,在我从一个简单的HTML演示构建一个有角度的应用程序时,我正在努力思考如何让ng include不使用额外的DOM元素。我正在使用非常纤细的HTML和完全开发的、紧密耦合的CSS(从SASS构建),重构是我想不惜一切代价避免的事情 以下是实际代码: 我需要是一个重复的元素,但有自己的逻辑和不同的内容。内容和重复次数都取决于业务逻辑。如您所见,在元素上放置ng控制器和ng repeat将不起作用。然而,插入一个新的DOM节点是可行的,这正是我试图避免的 我错过了什么?这是最佳实践还是有更好的方
我需要是一个重复的元素,但有自己的逻辑和不同的内容。内容和重复次数都取决于业务逻辑。如您所见,在元素上放置ng控制器和ng repeat将不起作用。然而,插入一个新的DOM节点是可行的,这正是我试图避免的
我错过了什么?这是最佳实践还是有更好的方法
编辑:正如评论中所要求的那样,我试图生成的最终HTML是:
...
来自控制器A和模板B的一些内容(例如…
)
来自同一控制器A和模板B的不同内容(例如…)
... (重复次数在控制器A中定义,例如通过某些服务)
...
我想使用相同的模板B(subheader.html)的原因是为了代码整洁。我设想subheader.html具有某种ng开关,以便返回动态内容
但基本上,底层静止是:有没有一种方法可以在不使用DOM节点的情况下透明地包含模板的内容
EDIT2:解决方案需要可重用。=) 您可以创建自定义指令,使用
templateUrl
属性链接到模板,并将replace
设置为true
:
app.directive('myDirective', function() {
return {
templateUrl: 'url/to/template',
replace: true,
link: function(scope, elem, attrs) {
}
}
});
这将包括模板,没有任何包装元素,没有任何包装范围。编辑:经过一些研究,为了完整性,我添加了一些信息。自1.1.4起,以下工作: 用法: 用法:
对于碰巧访问此问题的任何人: 从angular 1.1.4+开始,您可以使用templateURL中的函数使其成为动态的
检查另一个答案通过正确的设置,您可以定义自己的
ngInclude
指令,该指令可以运行,而不是Angular.js提供的指令,并防止内置指令永远执行
为了防止执行Angular内置指令,必须将指令的优先级设置为高于内置指令的优先级(400表示ngInclude
,并将终端
属性设置为true
之后,您需要提供一个post link函数,用于获取模板并用编译后的模板HTML替换元素的DOM节点
一句警告:这相当严厉,您为整个应用程序重新定义了ngInclude
的行为。因此,我将下面的指令设置为myApp
而不是myApp
,以限制其范围。如果您想在整个应用程序范围内使用它,您可能需要将其行为配置为le,例如,仅当HTML中设置了replace
属性时才替换元素,并且默认情况下返回到设置innerHtml
另外:这可能不适用于动画。原始的ngInclude
-指令的代码要长得多,因此如果在应用程序中使用动画,请c&p原始代码并将`$element.replaceWith()
嵌入其中
var includeDirective = ['$http', '$templateCache', '$sce', '$compile',
function($http, $templateCache, $sce, $compile) {
return {
restrict: 'ECA',
priority: 600,
terminal: true,
link: function(scope, $element, $attr) {
scope.$watch($sce.parseAsResourceUrl($attr.src), function ngIncludeWatchAction(src) {
if (src) {
$http.get(src, {cache: $templateCache}).success(function(response) {
var e =$compile(response)(scope);
$element.replaceWith(e);
});
}
});
}
};
}];
myApp.directive('ngInclude', includeDirective);
其他一些答案建议使用
replace:true
,但请记住,模板中的replace:true
相反,在中,我们找到了另一种选择:它允许您编写:
<div ng-include src="dynamicTemplatePath" include-replace></div>
(从另一个答案中删去“n”paste)现在确定您的要求是什么了,您可以为变体添加一个示例吗?很抱歉。编辑以澄清。您可以使用ng include作为标记
,而不是发出url
内容以外的标记。是的,但我正试图避免接触与DOM树紧密耦合的样式表(使用层次选择器)并使用nginclude将迫使我(因为生成的include模板成为ng include的子级)。有没有一种方法可以使templateUrl动态化,这样我就可以重复使用该指令?目前没有。至少没有现成的方法。我听说过一些我不推荐的解决方法。@filiptcI猜想你指的是:据我所知,angularjs>=1.1.4似乎是可能的,“可能在1.1.4+中”部分引用了$routeProvider
配置中的templateUrl
。但也许您可以在该线程之后找到一些有趣的内容。@filiptcI不得不争辩说,对于实际问题,我的解决方案仍然更好。如果这对您有效,那么很好。您的答案绝对正确,让我处于正确的位置Action(值得称赞!)。我只需要在整个模板结构中重复使用此功能。我不能为每个include声明一个新指令……这完全是另一回事(没有提到——或者我读得不好:)因为你基本上是用这个重新发明了ng include
,如果你在这一过程中遇到问题,请检查它的来源。干杯:)非常好(第二个例子)的解决方案!它甚至可以在元素上工作,而且它们不会被抛出表外:)!编辑:在第二个示例中将.data
添加到tplContent
tplContent
是一个HTTP响应对象,而不是字符串,因此$compile会阻塞它。请在发布前测试代码!无法处理动态内容(ng重复,…)。请更新并使用这个对我有用的首选答案:
<div include="myTplVariable"></div>
var includeDirective = ['$http', '$templateCache', '$sce', '$compile',
function($http, $templateCache, $sce, $compile) {
return {
restrict: 'ECA',
priority: 600,
terminal: true,
link: function(scope, $element, $attr) {
scope.$watch($sce.parseAsResourceUrl($attr.src), function ngIncludeWatchAction(src) {
if (src) {
$http.get(src, {cache: $templateCache}).success(function(response) {
var e =$compile(response)(scope);
$element.replaceWith(e);
});
}
});
}
};
}];
myApp.directive('ngInclude', includeDirective);
<div ng-include src="dynamicTemplatePath" include-replace></div>
app.directive('includeReplace', function () {
return {
require: 'ngInclude',
restrict: 'A', /* optional */
link: function (scope, el, attrs) {
el.replaceWith(el.children());
}
};
});