AngularJS ng如果未在$compile之后删除元素

AngularJS ng如果未在$compile之后删除元素,angularjs,angularjs-directive,angularjs-compile,Angularjs,Angularjs Directive,Angularjs Compile,我有一个指令,它执行以下操作: 向元素添加另一个指令属性 删除它自己的属性 对元素调用$compile(),使AngularJS重新编译元素,以便附加新指令 这很好,除非我还向元素添加ng if。请参阅此示例,并按照以下步骤进行演示 按+任意次数可添加到“计数”中 按0重置“计数” 再次按+任意次数 如果在步骤2之后条件不再为真,我希望在其ng后从DOM中删除“my test Showed”标记。相反,它会一直存在,在第3步之后,您会看到该消息的额外副本 我假设调用$compile($elem

我有一个指令,它执行以下操作:

  • 向元素添加另一个指令属性
  • 删除它自己的属性
  • 对元素调用
    $compile()
    ,使AngularJS重新编译元素,以便附加新指令
  • 这很好,除非我还向元素添加ng if。请参阅此示例,并按照以下步骤进行演示

  • +
    任意次数可添加到“计数”中
  • 0
    重置“计数”
  • 再次按
    +
    任意次数
  • 如果在步骤2之后条件不再为真,我希望在其
    ng后从DOM中删除“my test Showed”
    标记。相反,它会一直存在,在第3步之后,您会看到该消息的额外副本

    我假设调用
    $compile($element)($scope)产生了一些意想不到的结果,但我不明白这里发生了什么。有什么想法吗

    谢谢,
    David

    我不知道如何正确解释,但是如果ng向元素添加了一个新范围,即他自己的范围,请检查此问题以查看更多详细信息:。我尝试了ng show,它以您想要的方式工作:

    ng-show="count > 0"
    

    希望它有帮助=)

    据我所知,当您用0更改count的值时,您的指令在更改
    count的值之前被销毁。所以unremoved指令的计数值仍然是1


    如果使用ngShow而不是ngIf,则可以解决此问题。因为ngShow属性不会触发$destroy事件,也不会从视图中删除元素。因此该指令可以捕获该
    计数的新值。或者您可以使用
    prelink
    而不是
    link
    来捕获
    count
    值的更新

    正如其他人所回答的,简短的解决方案是使用
    ng show
    而不是
    ng if
    ,或者不要像那样使用
    $compile
    。撇开这一点不谈,您可能有很好的理由来解释为什么要像这样使用
    ng if
    $compile

    这个问题让我感兴趣,因为它使用了
    $compile
    ,并将作用域与
    ng if
    隔离。我做了一些实验,并将尝试解释我的发现

    我们已经知道
    ng if
    创建了一个隔离作用域,但是通过
    $compile
    ng if
    元素传递给它会创建另一个隔离作用域(并且会使新编译的
    ng if
    查看第一轮隔离作用域上的变量-指令的
    $scope
    值)

    为了重新迭代,我们有一些作用域看起来像([]中的值是scope.$id):

  • 主/外部控制器具有
    范围[2]

  • ng如果我的测试
    元素有
    ng如果
    查看
    范围[2]。计数
    并创建
    范围[3]

  • my test
    链接器因此具有
    $scope.$id==3

  • my test
    执行
    $compile
    -重新编译
    ng if
    元素:创建新的隔离
    范围[4]
    并查看
    范围[3]。计数

  • scope[2]时,count
    点击0-
    scope[3]
    得到
    $destromed
    (因为
    scope[3]
    是由仍在某处徘徊的第一个
    ng创建的)。。。但是元素是A。仍然存在,B。它的计数没有更新-为什么

  • 因为仍然存在的元素是
    $compiled
    的元素,它有A.an
    ng if
    查看
    范围[3]。count
    (现在是$destromed)和B.它自己的新隔离
    范围[4]
    (通过与父
    范围[3]
    重新编译
    ng if
    元素创建)

    是的。这是非常令人困惑的,你可能只是在问。。。我该怎么解决这个问题

    TL;博士

    最简单的解决方案:
    $element.removeAttr('ng-if')在执行
    $compile($element)($scope)之前


    如果您一直在关注,这是有效的,因为原始的
    ng If
    仍在查看
    范围[2]。count
    ,并且存在的元素不再获得第二个隔离范围。

    在发布之前,我也尝试了ng show,我同意它解决了简约示例中的问题。然而,在我真正的应用程序中,有些情况下需要实际使用ng if,例如表单输入在可见时是必需的。@DavidSmith现在我记得了。您可以使用
    prelink
    重命名该
    link
    属性。更改后,您的ngIf将能够捕获
    count
    的值。你可以用这种方法解决这个问题。这非常有帮助,谢谢。其他内置指令是否会创建类似ng if的隔离作用域?如果我在我的指令旁边使用ng repeat或甚至自定义/第三方指令,我可能会再次遇到同样的问题吗?很高兴它很有帮助!某些内置指令和第三方指令确实会创建隔离作用域。您只需查看计划使用的每个指令的文档。例如,说“此指令创建了新范围。”(在指令信息部分下)和一样,但您将看到(例如)没有。