Angular 设置 ngIf 的指令
Angular directive that sets ngIf
我的应用程序中有一些 DOM 元素加载起来相当昂贵,因此我一直在使用以下模式来确保在需要时才加载它们:
<div ng-if="someCondition || everShown" ng-show="someCondition">
本质上,这确保元素仅在 someCondition 为真时才添加到 DOM,然后它会保留在那里。但是,那里有相当多的重复逻辑,因此我想将逻辑提取到一个指令中。
这是我的尝试:
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;
}
});
});
}
};
}
};
}
用法将是:
<div ng-show="someCondition" if-ever-shown>
然而,即使 DOM 中的 ng-if 值按预期变化,Angular 也只是忽略了它上面的变化:如果没有之前的 ng-if,元素总是出现在 DOM 中,如果有以前的值,即使我更改它也总是观察到它。
我怎样才能在这里获得所需的行为?我可以从指令修改 ngIf 吗?否则,是否有其他方法可以确保元素不会添加到 DOM 直到 ng-show 条件至少一次为真?
谢谢!
$compile service 不会自动编译在编译阶段添加到元素的指令。任何新添加的指令都需要在 link 阶段手动编译:
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);
}
});
以上示例演示了一个名为 my-if
的自定义指令。它在编译阶段添加了一个 ng-if
指令,并在 link 阶段手动编译它。
请注意,它是作为高优先级 "terminal"
指令实现的,并且它删除了 my-if
属性,因此指令只编译一次。
我的应用程序中有一些 DOM 元素加载起来相当昂贵,因此我一直在使用以下模式来确保在需要时才加载它们:
<div ng-if="someCondition || everShown" ng-show="someCondition">
本质上,这确保元素仅在 someCondition 为真时才添加到 DOM,然后它会保留在那里。但是,那里有相当多的重复逻辑,因此我想将逻辑提取到一个指令中。
这是我的尝试:
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;
}
});
});
}
};
}
};
}
用法将是:
<div ng-show="someCondition" if-ever-shown>
然而,即使 DOM 中的 ng-if 值按预期变化,Angular 也只是忽略了它上面的变化:如果没有之前的 ng-if,元素总是出现在 DOM 中,如果有以前的值,即使我更改它也总是观察到它。
我怎样才能在这里获得所需的行为?我可以从指令修改 ngIf 吗?否则,是否有其他方法可以确保元素不会添加到 DOM 直到 ng-show 条件至少一次为真?
谢谢!
$compile service 不会自动编译在编译阶段添加到元素的指令。任何新添加的指令都需要在 link 阶段手动编译:
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);
}
});
以上示例演示了一个名为 my-if
的自定义指令。它在编译阶段添加了一个 ng-if
指令,并在 link 阶段手动编译它。
请注意,它是作为高优先级 "terminal"
指令实现的,并且它删除了 my-if
属性,因此指令只编译一次。