diff --git a/packages/ember-application/lib/system/application.js b/packages/ember-application/lib/system/application.js
index c06c03427ae..3bc29b4d604 100644
--- a/packages/ember-application/lib/system/application.js
+++ b/packages/ember-application/lib/system/application.js
@@ -331,6 +331,10 @@ var Application = Namespace.extend(DeferredMixin, {
buildDefaultInstance: function() {
var instance = this.buildInstance();
+ // For the default instance only, set the view registry to the global
+ // Ember.View.views hash for backwards-compatibility.
+ EmberView.views = instance.container.lookup('-view-registry:main');
+
// TODO2.0: Legacy support for App.__container__
// and global methods on App that rely on a single,
// default instance.
@@ -1006,6 +1010,10 @@ Application.reopenClass({
registry.register('view:select', SelectView);
registry.register('view:-outlet', OutletView);
+ registry.register('-view-registry:main', { create: function() { return {}; } });
+
+ registry.injection('view', '_viewRegistry', '-view-registry:main');
+
registry.register('view:default', _MetamorphView);
registry.register('view:toplevel', EmberView.extend());
diff --git a/packages/ember-application/tests/system/visit_test.js b/packages/ember-application/tests/system/visit_test.js
index 16d28dc0ac0..57bb8fbda56 100644
--- a/packages/ember-application/tests/system/visit_test.js
+++ b/packages/ember-application/tests/system/visit_test.js
@@ -2,6 +2,7 @@ import run from "ember-metal/run_loop";
import Application from "ember-application/system/application";
import ApplicationInstance from "ember-application/system/application-instance";
import Router from "ember-routing/system/router";
+import View from "ember-views/views/view";
import compile from "ember-template-compiler/system/compile";
function createApplication() {
@@ -82,4 +83,45 @@ if (Ember.FEATURES.isEnabled('ember-application-visit')) {
assert.ok(false, "The visit() promise was rejected: " + error);
});
});
+
+ QUnit.test("Views created via visit() are not added to the global views hash", function(assert) {
+ QUnit.expect(6);
+ QUnit.stop();
+
+ var app;
+
+ run(function() {
+ app = createApplication();
+ app.instanceInitializer({
+ name: 'register-application-template',
+ initialize: function(app) {
+ app.registry.register('template:application', compile('
Hello world
{{view "child"}}'));
+ app.registry.register('view:application', View.extend({
+ elementId: 'my-cool-app'
+ }));
+ app.registry.register('view:child', View.extend({
+ elementId: 'child-view'
+ }));
+ }
+ });
+ });
+
+ assert.equal(Ember.$('#qunit-fixture').children().length, 0, "there are no elements in the fixture element");
+
+ app.visit('/').then(function(instance) {
+ QUnit.start();
+ assert.ok(instance instanceof ApplicationInstance, "promise is resolved with an ApplicationInstance");
+
+ run(instance.view, 'appendTo', '#qunit-fixture');
+ assert.equal(Ember.$("#qunit-fixture > #my-cool-app h1").text(), "Hello world", "the application was rendered once the promise resolves");
+ assert.strictEqual(View.views['my-cool-app'], undefined, "view was not registered globally");
+ ok(instance.container.lookup('-view-registry:main')['my-cool-app'] instanceof View, "view was registered on the instance's view registry");
+ ok(instance.container.lookup('-view-registry:main')['child-view'] instanceof View, "child view was registered on the instance's view registry");
+
+ instance.destroy();
+ }, function(error) {
+ QUnit.start();
+ assert.ok(false, "The visit() promise was rejected: " + error);
+ });
+ });
}
diff --git a/packages/ember-views/lib/views/states/in_dom.js b/packages/ember-views/lib/views/states/in_dom.js
index 19c5b799e31..bbdc6588fb0 100644
--- a/packages/ember-views/lib/views/states/in_dom.js
+++ b/packages/ember-views/lib/views/states/in_dom.js
@@ -1,4 +1,3 @@
-import Ember from "ember-metal/core"; // Ember.assert
import create from 'ember-metal/platform/create';
import merge from "ember-metal/merge";
import EmberError from "ember-metal/error";
@@ -12,17 +11,12 @@ import hasElement from "ember-views/views/states/has_element";
var inDOM = create(hasElement);
-var View;
-
merge(inDOM, {
enter: function(view) {
- if (!View) { View = requireModule('ember-views/views/view')["default"]; } // ES6TODO: this sucks. Have to avoid cycles...
-
// Register the view for event handling. This hash is used by
// Ember.EventDispatcher to dispatch incoming events.
if (!view.isVirtual) {
- Ember.assert("Attempted to register a view with an id already in use: "+view.elementId, !View.views[view.elementId]);
- View.views[view.elementId] = view;
+ view._register();
}
Ember.runInDebug(function() {
@@ -33,10 +27,8 @@ merge(inDOM, {
},
exit: function(view) {
- if (!View) { View = requireModule('ember-views/views/view')["default"]; } // ES6TODO: this sucks. Have to avoid cycles...
-
if (!this.isVirtual) {
- delete View.views[view.elementId];
+ view._unregister();
}
},
diff --git a/packages/ember-views/lib/views/view.js b/packages/ember-views/lib/views/view.js
index 706b7272530..873a567b8ab 100644
--- a/packages/ember-views/lib/views/view.js
+++ b/packages/ember-views/lib/views/view.js
@@ -1305,6 +1305,10 @@ var View = CoreView.extend(
}
this._super.apply(this, arguments);
+
+ if (!this._viewRegistry) {
+ this._viewRegistry = View.views;
+ }
},
__defineNonEnumerable: function(property) {
@@ -1371,6 +1375,33 @@ var View = CoreView.extend(
return this.currentState.handleEvent(this, eventName, evt);
},
+ /**
+ Registers the view in the view registry, keyed on the view's `elementId`.
+ This is used by the EventDispatcher to locate the view in response to
+ events.
+
+ This method should only be called once the view has been inserted into the
+ DOM.
+
+ @method _register
+ @private
+ */
+ _register: function() {
+ Ember.assert("Attempted to register a view with an id already in use: "+this.elementId, !this._viewRegistry[this.elementId]);
+ this._viewRegistry[this.elementId] = this;
+ },
+
+ /**
+ Removes the view from the view registry. This should be called when the
+ view is removed from DOM.
+
+ @method _unregister
+ @private
+ */
+ _unregister: function() {
+ delete this._viewRegistry[this.elementId];
+ },
+
registerObserver: function(root, path, target, observer) {
if (!observer && 'function' === typeof target) {
observer = target;