@@ -5844,7 +5844,9 @@ describe('$compile', function() {
5844
5844
5845
5845
testCleanup ( ) ;
5846
5846
5847
- expect ( cleanedCount ) . toBe ( xs . length ) ;
5847
+ // The ng-repeat template is removed/cleaned (the +1)
5848
+ // and each clone of the ng-repeat template is also removed (xs.length)
5849
+ expect ( cleanedCount ) . toBe ( xs . length + 1 ) ;
5848
5850
5849
5851
// Restore the previous jQuery.cleanData.
5850
5852
jQuery . cleanData = currentCleanData ;
@@ -8587,4 +8589,126 @@ describe('$compile', function() {
8587
8589
expect ( element . hasClass ( 'fire' ) ) . toBe ( true ) ;
8588
8590
} ) ) ;
8589
8591
} ) ;
8592
+
8593
+ describe ( 'element replacement' , function ( ) {
8594
+ it ( 'should broadcast $destroy only on removed elements, not replaced' , function ( ) {
8595
+ var linkCalls = [ ] ;
8596
+ var destroyCalls = [ ] ;
8597
+
8598
+ module ( function ( $compileProvider ) {
8599
+ $compileProvider . directive ( 'replace' , function ( ) {
8600
+ return {
8601
+ multiElement : true ,
8602
+ replace : true ,
8603
+ templateUrl : 'template123'
8604
+ } ;
8605
+ } ) ;
8606
+
8607
+ $compileProvider . directive ( 'foo' , function ( ) {
8608
+ return {
8609
+ priority : 1 , // before the replace directive
8610
+ link : function ( $scope , $element , $attrs ) {
8611
+ linkCalls . push ( $attrs . foo ) ;
8612
+ $element . on ( '$destroy' , function ( ) {
8613
+ destroyCalls . push ( $attrs . foo ) ;
8614
+ } ) ;
8615
+ }
8616
+ } ;
8617
+ } ) ;
8618
+ } ) ;
8619
+
8620
+ inject ( function ( $compile , $templateCache , $rootScope ) {
8621
+ $templateCache . put ( 'template123' , '<p></p>' ) ;
8622
+
8623
+ $compile (
8624
+ '<div replace-start foo="1"><span foo="1.1"></span></div>' +
8625
+ '<div foo="2"><span foo="2.1"></span></div>' +
8626
+ '<div replace-end foo="3"><span foo="3.1"></span></div>'
8627
+ ) ( $rootScope ) ;
8628
+
8629
+ expect ( linkCalls ) . toEqual ( [ '2' , '3' ] ) ;
8630
+ expect ( destroyCalls ) . toEqual ( [ ] ) ;
8631
+ $rootScope . $apply ( ) ;
8632
+ expect ( linkCalls ) . toEqual ( [ '2' , '3' , '1' ] ) ;
8633
+ expect ( destroyCalls ) . toEqual ( [ '2' , '3' ] ) ;
8634
+ } ) ;
8635
+ } ) ;
8636
+
8637
+ function getAll ( $root ) {
8638
+ // check for .querySelectorAll to support comment nodes
8639
+ return [ $root [ 0 ] ] . concat ( $root [ 0 ] . querySelectorAll ? sliceArgs ( $root [ 0 ] . querySelectorAll ( '*' ) ) : [ ] ) ;
8640
+ }
8641
+
8642
+ function testCompileLinkDataCleanup ( template ) {
8643
+ inject ( function ( $compile , $rootScope ) {
8644
+ var toCompile = jqLite ( template ) ;
8645
+
8646
+ var preCompiledChildren = getAll ( toCompile ) ;
8647
+ forEach ( preCompiledChildren , function ( element , i ) {
8648
+ jqLite . data ( element , 'foo' , 'template#' + i ) ;
8649
+ } ) ;
8650
+
8651
+ var linkedElements = $compile ( toCompile ) ( $rootScope ) ;
8652
+ $rootScope . $apply ( ) ;
8653
+ linkedElements . remove ( ) ;
8654
+
8655
+ forEach ( preCompiledChildren , function ( element , i ) {
8656
+ expect ( jqLite . hasData ( element ) ) . toBe ( false , "template#" + i ) ;
8657
+ } ) ;
8658
+ forEach ( getAll ( linkedElements ) , function ( element , i ) {
8659
+ expect ( jqLite . hasData ( element ) ) . toBe ( false , "linked#" + i ) ;
8660
+ } ) ;
8661
+ } ) ;
8662
+ }
8663
+ it ( 'should clean data of element-transcluded link-cloned elements' , function ( ) {
8664
+ testCompileLinkDataCleanup ( '<div><div ng-repeat-start="i in [1,2]"><span></span></div><div ng-repeat-end></div></div>' ) ;
8665
+ } ) ;
8666
+ it ( 'should clean data of element-transcluded elements' , function ( ) {
8667
+ testCompileLinkDataCleanup ( '<div ng-if-start="false"><span><span/></div><span></span><div ng-if-end><span></span></div>' ) ;
8668
+ } ) ;
8669
+
8670
+ function testReplaceElementCleanup ( dirOptions ) {
8671
+ var template = '<div></div>' ;
8672
+ module ( function ( $compileProvider ) {
8673
+ $compileProvider . directive ( 'theDir' , function ( ) {
8674
+ return {
8675
+ multiElement : true ,
8676
+ replace : dirOptions . replace ,
8677
+ transclude : dirOptions . transclude ,
8678
+ template : dirOptions . asyncTemplate ? undefined : template ,
8679
+ templateUrl : dirOptions . asyncTemplate ? 'the-dir-template-url' : undefined
8680
+ } ;
8681
+ } ) ;
8682
+ } ) ;
8683
+ inject ( function ( $templateCache , $compile , $rootScope ) {
8684
+ $templateCache . put ( 'the-dir-template-url' , template ) ;
8685
+
8686
+ testCompileLinkDataCleanup (
8687
+ '<div>' +
8688
+ '<div the-dir-start><span></span></div>' +
8689
+ '<div><span></span><span></span></div>' +
8690
+ '<div the-dir-end><span></span></div>' +
8691
+ '</div>'
8692
+ ) ;
8693
+ } ) ;
8694
+ }
8695
+ it ( 'should clean data of elements removed for directive template' , function ( ) {
8696
+ testReplaceElementCleanup ( { } ) ;
8697
+ } ) ;
8698
+ it ( 'should clean data of elements removed for directive templateUrl' , function ( ) {
8699
+ testReplaceElementCleanup ( { asyncTmeplate : true } ) ;
8700
+ } ) ;
8701
+ it ( 'should clean data of elements transcluded into directive template' , function ( ) {
8702
+ testReplaceElementCleanup ( { transclude : true } ) ;
8703
+ } ) ;
8704
+ it ( 'should clean data of elements transcluded into directive templateUrl' , function ( ) {
8705
+ testReplaceElementCleanup ( { transclude : true , asyncTmeplate : true } ) ;
8706
+ } ) ;
8707
+ it ( 'should clean data of elements replaced with directive template' , function ( ) {
8708
+ testReplaceElementCleanup ( { replace : true } ) ;
8709
+ } ) ;
8710
+ it ( 'should clean data of elements replaced with directive templateUrl' , function ( ) {
8711
+ testReplaceElementCleanup ( { replace : true , asyncTemplate : true } ) ;
8712
+ } ) ;
8713
+ } ) ;
8590
8714
} ) ;
0 commit comments