AngularJS ng-if 在 $compile 后不删除元素
AngularJS ng-if not deleting element after $compile
我有一个执行以下操作的指令:
- 向元素添加另一个指令属性。
- 删除自己的属性。
- 在元素上调用
$compile()
使 AngularJS 重新编译元素以便附加新指令。
这很好用,除非我还向元素添加了 ng-if。请参阅这个最小示例并按照以下步骤进行演示。
https://embed.plnkr.co/ymk0RwGopGF1KvesWmvA/
- 按
+
任意次数添加到 "count"。
- 按
0
重置"count"。
- 再次按
+
任意次数。
我希望 "my-test shown" <p>
标记从 DOM 中删除,一旦它的 ng-if
条件在步骤 #2 后不再为真。相反,它会保留下来,您会在步骤 #3 后看到该消息的额外副本。
我假设在 my-test 指令 link 函数中调用 $compile($element)($scope);
会产生一些意想不到的后果,但我不明白这里发生了什么。有什么想法吗?
谢谢,
大卫
我不知道如何正确解释,但 ng-if 为元素添加了一个新的范围,他自己的范围,检查这个问题以查看更多详细信息:what is the difference between ng-if and ng-show/ng-hide。我试过 ng-show 并且它按照你想要的方式工作:
ng-show="count > 0"
希望对您有所帮助=)
据我所知,当您将 count 的值更改为 0 时,您的指令会在更改 count
的值之前被销毁。所以未删除的指令的计数值仍然是 1.
如果你使用ngShow而不是ngIf,你可以解决这个问题。因为 ngShow 属性不会触发 $destroy 事件,也不会从您的视图中删除元素。因此该指令可以捕获 count
的新值。或者您可以使用 prelink
而不是 link
来捕获 count
值的更新。
正如其他人回答的那样,简短的解决方案是使用 ng-show
而不是 ng-if
或不使用 $compile
那样。除此之外,您可能有充分的理由为什么要像这样使用 ng-if
和 $compile
。
这个问题让我对使用 $compile
和 ng-if
的隔离范围感兴趣。我用 this fork 做了一些试验,并将尝试解释我的发现。
我们已经知道 ng-if
创建了一个隔离范围,但是随后通过 $compile
传递带有 ng-if
的元素创建 另一个 隔离作用域(并且会使新编译的 ng-if
在第一轮隔离作用域中查看变量——指令的 $scope
值)。
重申一下,我们有一些范围看起来像([] 中的值是范围。$id):
main/outer 控制器有 scope[2]
ng-if my-test
元素有 ng-if
查看 scope[2].count
并创建 scope[3]
my-test
链接器因此有 $scope.$id == 3;
my-test
执行 $compile
- 重新编译 ng-if
元素:创建新的隔离 scope[4]
并查看 scope[3].count
当 scope[2].count
命中 0 - scope[3]
得到 $destroyed
(因为 scope[3]
是由第一个 ng-if
创建的,它仍然是在某处徘徊)......但是!元素是 A. 仍然存在并且 B. 它的计数没有更新 - 为什么?
好吧,因为仍然存在的元素是 $compiled
并且有 A. 一个 ng-if
查看 scope[3].count
(现在 $destroyed)和 B. 它的自己的新隔离 scope[4]
(通过重新编译 ng-if
元素与父元素 scope[3]
创建)
所以你。这一切都非常令人困惑,您可能只是想问...我该如何解决这个问题?
TL;DR;
最简单的解决方案:
$element.removeAttr('ng-if');
在你做 $compile($element)($scope);
之前
如果您一直在关注,这会起作用,因为原始 ng-if
仍在查看 scope[2].count
,并且存在的元素不再获得第二个隔离范围。
我有一个执行以下操作的指令:
- 向元素添加另一个指令属性。
- 删除自己的属性。
- 在元素上调用
$compile()
使 AngularJS 重新编译元素以便附加新指令。
这很好用,除非我还向元素添加了 ng-if。请参阅这个最小示例并按照以下步骤进行演示。
https://embed.plnkr.co/ymk0RwGopGF1KvesWmvA/
- 按
+
任意次数添加到 "count"。 - 按
0
重置"count"。 - 再次按
+
任意次数。
我希望 "my-test shown" <p>
标记从 DOM 中删除,一旦它的 ng-if
条件在步骤 #2 后不再为真。相反,它会保留下来,您会在步骤 #3 后看到该消息的额外副本。
我假设在 my-test 指令 link 函数中调用 $compile($element)($scope);
会产生一些意想不到的后果,但我不明白这里发生了什么。有什么想法吗?
谢谢, 大卫
我不知道如何正确解释,但 ng-if 为元素添加了一个新的范围,他自己的范围,检查这个问题以查看更多详细信息:what is the difference between ng-if and ng-show/ng-hide。我试过 ng-show 并且它按照你想要的方式工作:
ng-show="count > 0"
希望对您有所帮助=)
据我所知,当您将 count 的值更改为 0 时,您的指令会在更改 count
的值之前被销毁。所以未删除的指令的计数值仍然是 1.
如果你使用ngShow而不是ngIf,你可以解决这个问题。因为 ngShow 属性不会触发 $destroy 事件,也不会从您的视图中删除元素。因此该指令可以捕获 count
的新值。或者您可以使用 prelink
而不是 link
来捕获 count
值的更新。
正如其他人回答的那样,简短的解决方案是使用 ng-show
而不是 ng-if
或不使用 $compile
那样。除此之外,您可能有充分的理由为什么要像这样使用 ng-if
和 $compile
。
这个问题让我对使用 $compile
和 ng-if
的隔离范围感兴趣。我用 this fork 做了一些试验,并将尝试解释我的发现。
我们已经知道 ng-if
创建了一个隔离范围,但是随后通过 $compile
传递带有 ng-if
的元素创建 另一个 隔离作用域(并且会使新编译的 ng-if
在第一轮隔离作用域中查看变量——指令的 $scope
值)。
重申一下,我们有一些范围看起来像([] 中的值是范围。$id):
main/outer 控制器有
scope[2]
ng-if my-test
元素有ng-if
查看scope[2].count
并创建scope[3]
my-test
链接器因此有$scope.$id == 3;
my-test
执行$compile
- 重新编译ng-if
元素:创建新的隔离scope[4]
并查看scope[3].count
当
scope[2].count
命中 0 -scope[3]
得到$destroyed
(因为scope[3]
是由第一个ng-if
创建的,它仍然是在某处徘徊)......但是!元素是 A. 仍然存在并且 B. 它的计数没有更新 - 为什么?
好吧,因为仍然存在的元素是 $compiled
并且有 A. 一个 ng-if
查看 scope[3].count
(现在 $destroyed)和 B. 它的自己的新隔离 scope[4]
(通过重新编译 ng-if
元素与父元素 scope[3]
创建)
所以你。这一切都非常令人困惑,您可能只是想问...我该如何解决这个问题?
TL;DR;
最简单的解决方案:
$element.removeAttr('ng-if');
在你做 $compile($element)($scope);
如果您一直在关注,这会起作用,因为原始 ng-if
仍在查看 scope[2].count
,并且存在的元素不再获得第二个隔离范围。