@@ -5820,7 +5820,9 @@ describe('$compile', function() {
5820
5820
5821
5821
testCleanup ( ) ;
5822
5822
5823
- expect ( cleanedCount ) . toBe ( xs . length ) ;
5823
+ // The ng-repeat template is removed/cleaned (the +1)
5824
+ // and each clone of the ng-repeat template is also removed (xs.length)
5825
+ expect ( cleanedCount ) . toBe ( xs . length + 1 ) ;
5824
5826
5825
5827
// Restore the previous jQuery.cleanData.
5826
5828
jQuery . cleanData = currentCleanData ;
@@ -8016,4 +8018,126 @@ describe('$compile', function() {
8016
8018
expect ( element . hasClass ( 'fire' ) ) . toBe ( true ) ;
8017
8019
} ) ) ;
8018
8020
} ) ;
8021
+
8022
+ describe ( 'element replacement' , function ( ) {
8023
+ it ( 'should broadcast $destroy only on removed elements, not replaced' , function ( ) {
8024
+ var linkCalls = [ ] ;
8025
+ var destroyCalls = [ ] ;
8026
+
8027
+ module ( function ( $compileProvider ) {
8028
+ $compileProvider . directive ( 'replace' , function ( ) {
8029
+ return {
8030
+ multiElement : true ,
8031
+ replace : true ,
8032
+ templateUrl : 'template123'
8033
+ } ;
8034
+ } ) ;
8035
+
8036
+ $compileProvider . directive ( 'foo' , function ( ) {
8037
+ return {
8038
+ priority : 1 , // before the replace directive
8039
+ link : function ( $scope , $element , $attrs ) {
8040
+ linkCalls . push ( $attrs . foo ) ;
8041
+ $element . on ( '$destroy' , function ( ) {
8042
+ destroyCalls . push ( $attrs . foo ) ;
8043
+ } ) ;
8044
+ }
8045
+ } ;
8046
+ } ) ;
8047
+ } ) ;
8048
+
8049
+ inject ( function ( $compile , $templateCache , $rootScope ) {
8050
+ $templateCache . put ( 'template123' , '<p></p>' ) ;
8051
+
8052
+ $compile (
8053
+ '<div replace-start foo="1"><span foo="1.1"></span></div>' +
8054
+ '<div foo="2"><span foo="2.1"></span></div>' +
8055
+ '<div replace-end foo="3"><span foo="3.1"></span></div>'
8056
+ ) ( $rootScope ) ;
8057
+
8058
+ expect ( linkCalls ) . toEqual ( [ '2' , '3' ] ) ;
8059
+ expect ( destroyCalls ) . toEqual ( [ ] ) ;
8060
+ $rootScope . $apply ( ) ;
8061
+ expect ( linkCalls ) . toEqual ( [ '2' , '3' , '1' ] ) ;
8062
+ expect ( destroyCalls ) . toEqual ( [ '2' , '3' ] ) ;
8063
+ } ) ;
8064
+ } ) ;
8065
+
8066
+ function getAll ( $root ) {
8067
+ // check for .querySelectorAll to support comment nodes
8068
+ return [ $root [ 0 ] ] . concat ( $root [ 0 ] . querySelectorAll ? sliceArgs ( $root [ 0 ] . querySelectorAll ( '*' ) ) : [ ] ) ;
8069
+ }
8070
+
8071
+ function testCompileLinkDataCleanup ( template ) {
8072
+ inject ( function ( $compile , $rootScope ) {
8073
+ var toCompile = jqLite ( template ) ;
8074
+
8075
+ var preCompiledChildren = getAll ( toCompile ) ;
8076
+ forEach ( preCompiledChildren , function ( element , i ) {
8077
+ jqLite . data ( element , 'foo' , 'template#' + i ) ;
8078
+ } ) ;
8079
+
8080
+ var linkedElements = $compile ( toCompile ) ( $rootScope ) ;
8081
+ $rootScope . $apply ( ) ;
8082
+ linkedElements . remove ( ) ;
8083
+
8084
+ forEach ( preCompiledChildren , function ( element , i ) {
8085
+ expect ( jqLite . hasData ( element ) ) . toBe ( false , "template#" + i ) ;
8086
+ } ) ;
8087
+ forEach ( getAll ( linkedElements ) , function ( element , i ) {
8088
+ expect ( jqLite . hasData ( element ) ) . toBe ( false , "linked#" + i ) ;
8089
+ } ) ;
8090
+ } ) ;
8091
+ }
8092
+ it ( 'should clean data of element-transcluded link-cloned elements' , function ( ) {
8093
+ testCompileLinkDataCleanup ( '<div><div ng-repeat-start="i in [1,2]"><span></span></div><div ng-repeat-end></div></div>' ) ;
8094
+ } ) ;
8095
+ it ( 'should clean data of element-transcluded elements' , function ( ) {
8096
+ testCompileLinkDataCleanup ( '<div ng-if-start="false"><span><span/></div><span></span><div ng-if-end><span></span></div>' ) ;
8097
+ } ) ;
8098
+
8099
+ function testReplaceElementCleanup ( dirOptions ) {
8100
+ var template = '<div></div>' ;
8101
+ module ( function ( $compileProvider ) {
8102
+ $compileProvider . directive ( 'theDir' , function ( ) {
8103
+ return {
8104
+ multiElement : true ,
8105
+ replace : dirOptions . replace ,
8106
+ transclude : dirOptions . transclude ,
8107
+ template : dirOptions . asyncTemplate ? undefined : template ,
8108
+ templateUrl : dirOptions . asyncTemplate ? 'the-dir-template-url' : undefined
8109
+ } ;
8110
+ } ) ;
8111
+ } ) ;
8112
+ inject ( function ( $templateCache , $compile , $rootScope ) {
8113
+ $templateCache . put ( 'the-dir-template-url' , template ) ;
8114
+
8115
+ testCompileLinkDataCleanup (
8116
+ '<div>' +
8117
+ '<div the-dir-start><span></span></div>' +
8118
+ '<div><span></span><span></span></div>' +
8119
+ '<div the-dir-end><span></span></div>' +
8120
+ '</div>'
8121
+ ) ;
8122
+ } ) ;
8123
+ }
8124
+ it ( 'should clean data of elements removed for directive template' , function ( ) {
8125
+ testReplaceElementCleanup ( { } ) ;
8126
+ } ) ;
8127
+ it ( 'should clean data of elements removed for directive templateUrl' , function ( ) {
8128
+ testReplaceElementCleanup ( { asyncTmeplate : true } ) ;
8129
+ } ) ;
8130
+ it ( 'should clean data of elements transcluded into directive template' , function ( ) {
8131
+ testReplaceElementCleanup ( { transclude : true } ) ;
8132
+ } ) ;
8133
+ it ( 'should clean data of elements transcluded into directive templateUrl' , function ( ) {
8134
+ testReplaceElementCleanup ( { transclude : true , asyncTmeplate : true } ) ;
8135
+ } ) ;
8136
+ it ( 'should clean data of elements replaced with directive template' , function ( ) {
8137
+ testReplaceElementCleanup ( { replace : true } ) ;
8138
+ } ) ;
8139
+ it ( 'should clean data of elements replaced with directive templateUrl' , function ( ) {
8140
+ testReplaceElementCleanup ( { replace : true , asyncTemplate : true } ) ;
8141
+ } ) ;
8142
+ } ) ;
8019
8143
} ) ;
0 commit comments