设置 ngIf 的 Angular 指令 [英] Angular directive that sets ngIf
问题描述
我的应用程序中有一些 DOM 元素加载起来相当昂贵,因此我一直使用以下模式来确保它们在需要时才加载:
本质上,这确保元素仅在 someCondition 为真时才添加到 DOM 中,然后保持在那里.但是,那里有相当多的重复逻辑,因此我想将逻辑提取到指令中.
这是我的尝试:
导出函数 IfEverShown($parse: angular.IParseService): angular.IDirective {返回 {限制:A",编译:函数(元素:angular.IAugmentedJQuery,属性:angular.IAttributes) {如果(!属性[ngShow"]){返回;}element.attr("ng-if", "everShown");返回 {前:功能(范围:angular.IScope){范围["everShown"] = false;attributes.$observe('ngShow', function (expr) {范围.$watch(函数(){返回 $parse(<any> expr)(scope);}, 函数(值){如果(值){范围["everShown"] = true;}});});}};}};}
那么用法是:
然而,即使 DOM 中的 ng-if 值按预期更改,Angular 也会简单地忽略其上的更改:如果之前没有 ng-if,则该元素始终存在于 DOM 中,如果有以前的值,即使我改变它也总是能观察到.
我怎么能在这里得到想要的行为?我可以从指令修改 ngIf 吗?否则,是否有其他方法可以确保在 ng-show 条件至少为真一次之前元素不会被添加到 DOM 中?
谢谢!
解决方案 $编译服务不会自动编译在编译阶段添加到元素的指令.任何新添加的指令都需要在链接阶段手动编译:
app.directive("myIf", function($compile) {返回 {优先级:1000,终端:真的,编译:函数(tElem,tAttrs){tAttrs.$set("ngIf", tAttrs.myIf);tAttrs.$set("myIf", null);返回postLink;}}函数 postLink(scope, elem, attrs) {$compile(elem)(范围);}});
上面的示例演示了一个名为 my-if
的自定义指令.它在编译阶段添加了一个 ng-if
指令,并在链接阶段手动编译它.
请注意,它是作为高优先级的 "terminal"
指令实现的,并且它删除了 my-if
属性,以便指令仅编译一次.
I have a few DOM elements in my application that are fairly expensive to load, so I have been using the following pattern to ensure that they aren't loaded until needed:
<div ng-if="someCondition || everShown" ng-show="someCondition">
Essentially, that makes sure that the element is only added to the DOM once someCondition is true and then it remains there. However, there is a fair bit of repeated logic there and thus I wanted to extract the logic into a directive.
This has been my attempt:
export function IfEverShown($parse: angular.IParseService): angular.IDirective {
return {
restrict: "A",
compile: function(element: angular.IAugmentedJQuery,
attributes: angular.IAttributes) {
if (!attributes["ngShow"]) {
return;
}
element.attr("ng-if", "everShown");
return {
pre: function(scope: angular.IScope) {
scope["everShown"] = false;
attributes.$observe('ngShow', function (expr) {
scope.$watch(function () {
return $parse(<any> expr)(scope);
}, function (value) {
if (value) {
scope["everShown"] = true;
}
});
});
}
};
}
};
}
The usage would then be:
<div ng-show="someCondition" if-ever-shown>
However, even though the ng-if value in the DOM changes as expected, Angular simply ignores the changes on it: if there was no previous ng-if, the element is always present in the DOM, and if there was a previous value, it is always observed even after I change it.
How could I get the desired behavior here? Can I get to modify an ngIf from a directive? Otherwise, is there other way to ensure that the element doesn't get added to the DOM until the ng-show condition has been true at least once?
Thanks!
解决方案 The $compile service does not automatically compile directives added to the element during the compile phase. Any newly added directives need to be manually compiled in the link phase:
app.directive("myIf", function($compile) {
return {
priority: 1000,
terminal: true,
compile: function(tElem, tAttrs) {
tAttrs.$set("ngIf", tAttrs.myIf);
tAttrs.$set("myIf", null);
return postLink;
}
}
function postLink(scope, elem, attrs) {
$compile(elem)(scope);
}
});
The above example demonstrates a custom directive called my-if
. It adds an ng-if
directive during the compile phase and manually compiles it during the link phase.
Notice that it is implemented as a high priority "terminal"
directive and that it removes the my-if
attribute so that directives are compiled only once.
The DEMO on PLNKR.
这篇关于设置 ngIf 的 Angular 指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文