jQuery 如何替换 AngularJS 指令链接函数中的元素?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17090964/
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
How to replace an element in AngularJS directive linking function?
提问by Antonio Madonna
I'm creating a <row>
AngularJS directive that needs to replace itself (the <row>
tag must not be present in the DOM after execution) with a dynamic template that can contain any HTML code.
我正在创建一个<row>
AngularJS 指令,该指令需要<row>
用一个可以包含任何 HTML 代码的动态模板来替换自身(执行后标签不能出现在 DOM 中)。
The problem in using replace: true
is that it does not work with table's <tr>
tags and that the template is dynamically chosen.
使用中的问题replace: true
是它不适用于表格的<tr>
标签,并且模板是动态选择的。
So I'm trying to find a way to replace the element in the linking function, with no success.
所以我试图找到一种方法来替换链接函数中的元素,但没有成功。
Using jQuery's .replaceWith()
breaks ngRepeat
for unknown reason.
出于未知原因使用 jQuery 的.replaceWith()
中断ngRepeat
。
Any hints?
任何提示?
Here is the fiddle
这是小提琴
回答by pilau
Mark's answer will work, however, that example is too limited to show the whole picture. Whereas Mark's directive might indeed suffice for common and simple UI components, for more complex operations, that pattern is one to be avoided. Below I explain in detailthe reason behind this. In fact, Angular alreadyprovides a far simpler way to replace the directive element with a template. It can be found at the bottom of this answer.
马克的答案会起作用,但是,该示例太有限而无法显示全貌。尽管 Mark 的指令对于常见和简单的 UI 组件可能确实足够了,但对于更复杂的操作,这种模式是应该避免的。下面我详细解释一下这背后的原因。事实上,Angular已经提供了一种更简单的方法来用模板替换指令元素。它可以在这个答案的底部找到。
Here is how a directive looks behind the scenes:
以下是指令在幕后的样子:
.directive('row', function ($compile) {
return {
restrict: 'E',
scope: {
items: "="
},
// Whether you define it this way or not, this is the order of
// operation (execution) behind every AngularJS directive.
// When you use the more simple syntax, Angular actually generates this
// structure for you (this is done by the $compile service):
compile: function CompilingFunction($templateElement, $templateAttributes, transcludeFn) {
// The compile function hooks you up into the DOM before any scope is
// applied onto the template. It allows you to read attributes from
// the directive expression (i.e. tag name, attribute, class name or
// comment) and manipulate the DOM (and only the DOM) as you wish.
// When you let Angular generate this portion for you, it basically
// appends your template into the DOM, and then some ("some" includes
// the transclude operation, but that's out of the $scope of my answer ;) )
return function LinkingFunction($scope, $element, $attrs) {
// The link function is usually what we become familiar with when
// starting to learn how to use directives. It gets fired after
// the template has been compiled, providing you a space to
// manipulate the directive's scope as well as DOM elements.
var html ='<div ng-repeat="item in items">I should not be red</div>';
var e = $compile(html)($scope);
$element.replaceWith(e);
};
}
};
});
What can we make out of that? It is obvious then, that manually calling $compile
for the same DOM layout twiceis redundant, bad for performance andbad for your teeth, too. What should you do instead? Simply compile your DOM where it shouldbe compiled:
我们能从中得到什么?很明显,两次手动调用$compile
相同的 DOM 布局是多余的,对性能和牙齿也不利。你应该怎么做?只需在应该编译的地方编译 DOM :
.directive('row', function ($compile) {
return {
restrict: 'E',
template: '<div ng-repeat="item in items">I should not be red</div>',
scope: {
items: "="
},
compile: function CompilingFunction($templateElement, $templateAttributes) {
$templateElement.replaceWith(this.template);
return function LinkingFunction($scope, $element, $attrs) {
// play with the $scope here, if you need too.
};
}
};
});
If you want to dive in further under the hood of directives, here is what I like to call the Unofficial AngularJS Directive Reference
如果你想深入了解指令,这里是我喜欢称之为非官方AngularJS 指令参考的内容
Once you're done with that head over here: https://github.com/angular/angular.js/wiki/Understanding-Directives
一旦你完成了这个头在这里:https: //github.com/angular/angular.js/wiki/Understanding-Directives
Now, as promised, here is the solution you came here for:
现在,正如所承诺的,这是您来到这里的解决方案:
Using replace: true
:
使用replace: true
:
.directive('row', function ($compile) {
return {
restrict: 'E',
template: '<div ng-repeat="item in items">I should not be red</div>',
replace: true,
scope: {
items: "="
}
};
});
回答by Mark Coleman
Your fiddle seems pretty basic but you should be able to just use outerHTML
你的小提琴看起来很基本,但你应该能够使用 outerHTML
element[0].outerHTML ='<div>I should not be red</div>';
If you have to deal with ng-repeat
you can bind your items to a scope property and reference them in your template that you compile. Once it is compiled you can use jQuery replaceWith()
如果您必须处理,ng-repeat
您可以将您的项目绑定到范围属性并在您编译的模板中引用它们。编译完成后,您可以使用 jQueryreplaceWith()
html
html
<row items="items">***</row>
directive
指示
.directive('row', function ($compile) {
return {
restrict: 'E',
scope: {
items: "="
},
link: function (scope, element, attrs) {
var html ='<div ng-repeat="item in items">I should not be red</div>';
var e =$compile(html)(scope);
element.replaceWith(e);
}
};
});