diff --git a/packages/ember-htmlbars/tests/integration/will-destroy-element-hook-test.js b/packages/ember-htmlbars/tests/integration/will-destroy-element-hook-test.js
new file mode 100644
index 00000000000..987f17fd0f3
--- /dev/null
+++ b/packages/ember-htmlbars/tests/integration/will-destroy-element-hook-test.js
@@ -0,0 +1,57 @@
+import run from 'ember-metal/run_loop';
+import Component from 'ember-views/views/component';
+import compile from 'ember-template-compiler/system/compile';
+import { runAppend, runDestroy } from "ember-runtime/tests/utils";
+
+import { set } from 'ember-metal/property_set';
+
+var component;
+
+QUnit.module('ember-htmlbars: destroy-element-hook tests', {
+ teardown() {
+ runDestroy(component);
+ }
+});
+
+QUnit.test('willDestroyElement is only called once when a component leaves scope', function(assert) {
+ var innerChild, innerChildDestroyed;
+
+ component = Component.create({
+ switch: true,
+
+ layout: compile(`
+ {{~#if switch~}}
+ {{~#view innerChild}}Truthy{{/view~}}
+ {{~/if~}}
+ `),
+
+ innerChild: Component.extend({
+ init() {
+ this._super(...arguments);
+ innerChild = this;
+ },
+
+ willDestroyElement() {
+ if (innerChildDestroyed) {
+ throw new Error('willDestroyElement has already been called!!');
+ } else {
+ innerChildDestroyed = true;
+ }
+ }
+ })
+ });
+
+ runAppend(component);
+
+ assert.equal(component.$().text(), 'Truthy', 'precond - truthy template is displayed');
+ assert.equal(component.get('childViews.length'), 1);
+
+ run(function() {
+ set(component, 'switch', false);
+ });
+
+ run(function() {
+ assert.equal(innerChild.get('isDestroyed'), true, 'the innerChild has been destroyed');
+ assert.equal(component.$().text(), '', 'truthy template is removed');
+ });
+});
diff --git a/packages/ember-metal-views/lib/renderer.js b/packages/ember-metal-views/lib/renderer.js
index bfa37b29b3a..c29a7976e07 100755
--- a/packages/ember-metal-views/lib/renderer.js
+++ b/packages/ember-metal-views/lib/renderer.js
@@ -231,14 +231,7 @@ Renderer.prototype.willDestroyElement = function (view) {
}
if (view._transitionTo) {
- view._transitionTo('destroying', false);
- }
-
- var childViews = view.childViews;
- if (childViews) {
- for (var i = 0; i < childViews.length; i++) {
- this.willDestroyElement(childViews[i]);
- }
+ view._transitionTo('destroying');
}
};
@@ -253,11 +246,8 @@ Renderer.prototype.didDestroyElement = function (view) {
view._transitionTo('preRender');
}
- var childViews = view.childViews;
- if (childViews) {
- for (var i = 0; i < childViews.length; i++) {
- this.didDestroyElement(childViews[i]);
- }
+ if (view.trigger) {
+ view.trigger('didDestroyElement');
}
}; // element destroyed so view.destroy shouldn't try to remove it removedFromDOM
diff --git a/packages/ember-views/lib/mixins/view_state_support.js b/packages/ember-views/lib/mixins/view_state_support.js
index 1f49573e983..bd7e894624e 100644
--- a/packages/ember-views/lib/mixins/view_state_support.js
+++ b/packages/ember-views/lib/mixins/view_state_support.js
@@ -2,12 +2,12 @@ import Ember from 'ember-metal/core';
import { Mixin } from "ember-metal/mixin";
var ViewStateSupport = Mixin.create({
- transitionTo(state, children) {
+ transitionTo(state) {
Ember.deprecate("Ember.View#transitionTo has been deprecated, it is for internal use only");
- this._transitionTo(state, children);
+ this._transitionTo(state);
},
- _transitionTo(state, children) {
+ _transitionTo(state) {
var priorState = this.currentState;
var currentState = this.currentState = this._states[state];
this._state = state;
diff --git a/packages/ember-views/lib/views/container_view.js b/packages/ember-views/lib/views/container_view.js
index 41df4f0e89c..a2d376091ae 100644
--- a/packages/ember-views/lib/views/container_view.js
+++ b/packages/ember-views/lib/views/container_view.js
@@ -9,6 +9,7 @@ import {
observer,
beforeObserver
} from "ember-metal/mixin";
+import { on } from "ember-metal/events";
import containerViewTemplate from "ember-htmlbars/templates/container-view";
containerViewTemplate.meta.revision = 'Ember@VERSION_STRING_PLACEHOLDER';
@@ -280,8 +281,26 @@ var ContainerView = View.extend(MutableArray, {
},
objectAt(idx) {
- return get(this, 'childViews')[idx];
- }
+ return this.childViews[idx];
+ },
+
+ _triggerChildWillDestroyElement: on('willDestroyElement', function () {
+ var childViews = this.childViews;
+ if (childViews) {
+ for (var i = 0; i < childViews.length; i++) {
+ this.renderer.willDestroyElement(childViews[i]);
+ }
+ }
+ }),
+
+ _triggerChildDidDestroyElement: on('didDestroyElement', function () {
+ var childViews = this.childViews;
+ if (childViews) {
+ for (var i = 0; i < childViews.length; i++) {
+ this.renderer.didDestroyElement(childViews[i]);
+ }
+ }
+ })
});
export default ContainerView;