@@ -5676,7 +5676,9 @@ describe('$compile', function() {
5676
5676
5677
5677
testCleanup ( ) ;
5678
5678
5679
- expect ( cleanedCount ) . toBe ( xs . length ) ;
5679
+ // The ng-repeat template is removed/cleaned (the +1)
5680
+ // and each clone of the ng-repeat template is also removed (xs.length)
5681
+ expect ( cleanedCount ) . toBe ( xs . length + 1 ) ;
5680
5682
5681
5683
// Restore the previous jQuery.cleanData.
5682
5684
jQuery . cleanData = currentCleanData ;
@@ -7872,4 +7874,126 @@ describe('$compile', function() {
7872
7874
expect ( element . hasClass ( 'fire' ) ) . toBe ( true ) ;
7873
7875
} ) ) ;
7874
7876
} ) ;
7877
+
7878
+ describe ( 'element replacement' , function ( ) {
7879
+ it ( 'should broadcast $destroy only on removed elements, not replaced' , function ( ) {
7880
+ var linkCalls = [ ] ;
7881
+ var destroyCalls = [ ] ;
7882
+
7883
+ module ( function ( $compileProvider ) {
7884
+ $compileProvider . directive ( 'replace' , function ( ) {
7885
+ return {
7886
+ multiElement : true ,
7887
+ replace : true ,
7888
+ templateUrl : 'template123'
7889
+ } ;
7890
+ } ) ;
7891
+
7892
+ $compileProvider . directive ( 'foo' , function ( ) {
7893
+ return {
7894
+ priority : 1 , // before the replace directive
7895
+ link : function ( $scope , $element , $attrs ) {
7896
+ linkCalls . push ( $attrs . foo ) ;
7897
+ $element . on ( '$destroy' , function ( ) {
7898
+ destroyCalls . push ( $attrs . foo ) ;
7899
+ } ) ;
7900
+ }
7901
+ } ;
7902
+ } ) ;
7903
+ } ) ;
7904
+
7905
+ inject ( function ( $compile , $templateCache , $rootScope ) {
7906
+ $templateCache . put ( 'template123' , '<p></p>' ) ;
7907
+
7908
+ $compile (
7909
+ '<div replace-start foo="1"><span foo="1.1"></span></div>' +
7910
+ '<div foo="2"><span foo="2.1"></span></div>' +
7911
+ '<div replace-end foo="3"><span foo="3.1"></span></div>'
7912
+ ) ( $rootScope ) ;
7913
+
7914
+ expect ( linkCalls ) . toEqual ( [ '2' , '3' ] ) ;
7915
+ expect ( destroyCalls ) . toEqual ( [ ] ) ;
7916
+ $rootScope . $apply ( ) ;
7917
+ expect ( linkCalls ) . toEqual ( [ '2' , '3' , '1' ] ) ;
7918
+ expect ( destroyCalls ) . toEqual ( [ '2' , '3' ] ) ;
7919
+ } ) ;
7920
+ } ) ;
7921
+
7922
+ function getAll ( $root ) {
7923
+ // check for .querySelectorAll to support comment nodes
7924
+ return [ $root [ 0 ] ] . concat ( $root [ 0 ] . querySelectorAll ? sliceArgs ( $root [ 0 ] . querySelectorAll ( '*' ) ) : [ ] ) ;
7925
+ }
7926
+
7927
+ function testCompileLinkDataCleanup ( template ) {
7928
+ inject ( function ( $compile , $rootScope ) {
7929
+ var toCompile = jqLite ( template ) ;
7930
+
7931
+ var preCompiledChildren = getAll ( toCompile ) ;
7932
+ forEach ( preCompiledChildren , function ( element , i ) {
7933
+ jqLite . data ( element , 'foo' , 'template#' + i ) ;
7934
+ } ) ;
7935
+
7936
+ var linkedElements = $compile ( toCompile ) ( $rootScope ) ;
7937
+ $rootScope . $apply ( ) ;
7938
+ linkedElements . remove ( ) ;
7939
+
7940
+ forEach ( preCompiledChildren , function ( element , i ) {
7941
+ expect ( jqLite . hasData ( element ) ) . toBe ( false , "template#" + i ) ;
7942
+ } ) ;
7943
+ forEach ( getAll ( linkedElements ) , function ( element , i ) {
7944
+ expect ( jqLite . hasData ( element ) ) . toBe ( false , "linked#" + i ) ;
7945
+ } ) ;
7946
+ } ) ;
7947
+ }
7948
+ it ( 'should clean data of element-transcluded link-cloned elements' , function ( ) {
7949
+ testCompileLinkDataCleanup ( '<div><div ng-repeat-start="i in [1,2]"><span></span></div><div ng-repeat-end></div></div>' ) ;
7950
+ } ) ;
7951
+ it ( 'should clean data of element-transcluded elements' , function ( ) {
7952
+ testCompileLinkDataCleanup ( '<div ng-if-start="false"><span><span/></div><span></span><div ng-if-end><span></span></div>' ) ;
7953
+ } ) ;
7954
+
7955
+ function testReplaceElementCleanup ( dirOptions ) {
7956
+ var template = '<div></div>' ;
7957
+ module ( function ( $compileProvider ) {
7958
+ $compileProvider . directive ( 'theDir' , function ( ) {
7959
+ return {
7960
+ multiElement : true ,
7961
+ replace : dirOptions . replace ,
7962
+ transclude : dirOptions . transclude ,
7963
+ template : dirOptions . asyncTemplate ? undefined : template ,
7964
+ templateUrl : dirOptions . asyncTemplate ? 'the-dir-template-url' : undefined
7965
+ } ;
7966
+ } ) ;
7967
+ } ) ;
7968
+ inject ( function ( $templateCache , $compile , $rootScope ) {
7969
+ $templateCache . put ( 'the-dir-template-url' , template ) ;
7970
+
7971
+ testCompileLinkDataCleanup (
7972
+ '<div>' +
7973
+ '<div the-dir-start><span></span></div>' +
7974
+ '<div><span></span><span></span></div>' +
7975
+ '<div the-dir-end><span></span></div>' +
7976
+ '</div>'
7977
+ ) ;
7978
+ } ) ;
7979
+ }
7980
+ it ( 'should clean data of elements removed for directive template' , function ( ) {
7981
+ testReplaceElementCleanup ( { } ) ;
7982
+ } ) ;
7983
+ it ( 'should clean data of elements removed for directive templateUrl' , function ( ) {
7984
+ testReplaceElementCleanup ( { asyncTmeplate : true } ) ;
7985
+ } ) ;
7986
+ it ( 'should clean data of elements transcluded into directive template' , function ( ) {
7987
+ testReplaceElementCleanup ( { transclude : true } ) ;
7988
+ } ) ;
7989
+ it ( 'should clean data of elements transcluded into directive templateUrl' , function ( ) {
7990
+ testReplaceElementCleanup ( { transclude : true , asyncTmeplate : true } ) ;
7991
+ } ) ;
7992
+ it ( 'should clean data of elements replaced with directive template' , function ( ) {
7993
+ testReplaceElementCleanup ( { replace : true } ) ;
7994
+ } ) ;
7995
+ it ( 'should clean data of elements replaced with directive templateUrl' , function ( ) {
7996
+ testReplaceElementCleanup ( { replace : true , asyncTemplate : true } ) ;
7997
+ } ) ;
7998
+ } ) ;
7875
7999
} ) ;
0 commit comments