Permalink
Browse files

Add currentView property to Ember.ContainerView

  • Loading branch information...
Tom Dale
Tom Dale committed May 3, 2012
1 parent 3e9dd6c commit 00b8940af1c948dd1974be184e022269a87a461d
@@ -175,13 +175,34 @@ var childViewsProperty = Ember.computed(function() {
And the `Ember.View` instance stored in `aContainer.aView` will be removed from `aContainer`'s
`childViews` array.
## Templates and Layout
A `template`, `templateName`, `defaultTemplate`, `layout`, `layoutName` or `defaultLayout`
property on a container view will not result in the template or layout being rendered.
The HTML contents of a `Ember.ContainerView`'s DOM representation will only be the rendered HTML
of its child views.
## Binding a View to Display
If you would like to display a single view in your ContainerView, you can set its `currentView`
property. When the `currentView` property is set to a view instance, it will be added to the
ContainerView's `childViews` array. If the `currentView` property is later changed to a
different view, the new view will replace the old view. If `currentView` is set to `null`, the
last `currentView` will be removed.
This functionality is useful for cases where you want to bind the display of a ContainerView to
a controller or state manager. For example, you can bind the `currentView` of a container to
a controller like this:
// Controller
App.appController = Ember.Object.create({
view: Ember.View.create({
templateName: 'person_template'
})
});
// Handlebars template
{{view Ember.ContainerView currentViewBinding="App.appController.view"}}
@extends Ember.View

This comment has been minimized.

Show comment
Hide comment
@trek

trek May 3, 2012

Member

👍 doc writing.

@trek

trek May 3, 2012

Member

👍 doc writing.

*/
@@ -319,7 +340,27 @@ Ember.ContainerView = Ember.View.extend({
} else {
this.domManager.prepend(this, view);
}
}
},
currentView: null,
_currentViewWillChange: Ember.beforeObserver(function() {
var childViews = get(this, 'childViews'),
currentView = get(this, 'currentView');
if (currentView) {
childViews.removeObject(currentView);
}
}, 'currentView'),
_currentViewDidChange: Ember.observer(function() {
var childViews = get(this, 'childViews'),
currentView = get(this, 'currentView');
if (currentView) {
childViews.pushObject(currentView);
}
}, 'currentView')
});
// Ember.ContainerView extends the default view states to provide different
@@ -1,11 +1,10 @@
var get = Ember.get, getPath = Ember.getPath;
var get = Ember.get, getPath = Ember.getPath, set = Ember.set;
module("ember-views/views/container_view_test");
test("should be able to insert views after the DOM representation is created", function() {
var container = Ember.ContainerView.create({
classNameBindings: ['name'],
name: 'foo'
});
@@ -112,3 +111,140 @@ test("views that are removed from a ContainerView should have their child views
});
equal(getPath(view, 'childViews.length'), 0, "child views are cleared when removed from container view");
});
test("if a ContainerView starts with an empy currentView, nothing is displayed", function() {
var container = Ember.ContainerView.create();
Ember.run(function() {
container.appendTo('#qunit-fixture');
});
equal(container.$().text(), '', "has a empty contents");
equal(getPath(container, 'childViews.length'), 0, "should not have any child views");
});
test("if a ContainerView starts with a currentView, it is rendered as a child view", function() {
var container = Ember.ContainerView.create();
var mainView = Ember.View.create({
template: function() {
return "This is the main view.";
}
});
set(container, 'currentView', mainView);
Ember.run(function() {
container.appendTo('#qunit-fixture');
});
equal(container.$().text(), "This is the main view.", "should render its child");
equal(getPath(container, 'childViews.length'), 1, "should have one child view");
equal(getPath(container, 'childViews').objectAt(0), mainView, "should have the currentView as the only child view");
});
test("if a ContainerView starts with no currentView and then one is set, the ContainerView is updated", function() {
var container = Ember.ContainerView.create();
var mainView = Ember.View.create({
template: function() {
return "This is the main view.";
}
});
Ember.run(function() {
container.appendTo('#qunit-fixture');
});
equal(container.$().text(), '', "has a empty contents");
equal(getPath(container, 'childViews.length'), 0, "should not have any child views");
Ember.run(function() {
set(container, 'currentView', mainView);
});
equal(container.$().text(), "This is the main view.", "should render its child");
equal(getPath(container, 'childViews.length'), 1, "should have one child view");
equal(getPath(container, 'childViews').objectAt(0), mainView, "should have the currentView as the only child view");
});
test("if a ContainerView starts with a currentView and then is set to null, the ContainerView is updated", function() {
var container = Ember.ContainerView.create();
var mainView = Ember.View.create({
template: function() {
return "This is the main view.";
}
});
container.set('currentView', mainView);
Ember.run(function() {
container.appendTo('#qunit-fixture');
});
equal(container.$().text(), "This is the main view.", "should render its child");
equal(getPath(container, 'childViews.length'), 1, "should have one child view");
equal(getPath(container, 'childViews').objectAt(0), mainView, "should have the currentView as the only child view");
Ember.run(function() {
set(container, 'currentView', null);
});
equal(container.$().text(), '', "has a empty contents");
equal(getPath(container, 'childViews.length'), 0, "should not have any child views");
});
test("if a ContainerView starts with a currentView and then is set to null, the ContainerView is updated", function() {
var container = Ember.ContainerView.create();
var mainView = Ember.View.create({
template: function() {
return "This is the main view.";
}
});
container.set('currentView', mainView);
Ember.run(function() {
container.appendTo('#qunit-fixture');
});
equal(container.$().text(), "This is the main view.", "should render its child");
equal(getPath(container, 'childViews.length'), 1, "should have one child view");
equal(getPath(container, 'childViews').objectAt(0), mainView, "should have the currentView as the only child view");
Ember.run(function() {
set(container, 'currentView', null);
});
equal(container.$().text(), '', "has a empty contents");
equal(getPath(container, 'childViews.length'), 0, "should not have any child views");
});
test("if a ContainerView starts with a currentView and then a different currentView is set, the old view is removed and the new one is added", function() {
var container = Ember.ContainerView.create();
var mainView = Ember.View.create({
template: function() {
return "This is the main view.";
}
});
var secondaryView = Ember.View.create({
template: function() {
return "This is the secondary view.";
}
});
container.set('currentView', mainView);
Ember.run(function() {
container.appendTo('#qunit-fixture');
});
equal(container.$().text(), "This is the main view.", "should render its child");
equal(getPath(container, 'childViews.length'), 1, "should have one child view");
equal(getPath(container, 'childViews').objectAt(0), mainView, "should have the currentView as the only child view");
Ember.run(function() {
set(container, 'currentView', secondaryView);
});
equal(container.$().text(), "This is the secondary view.", "should render its child");
equal(getPath(container, 'childViews.length'), 1, "should have one child view");
equal(getPath(container, 'childViews').objectAt(0), secondaryView, "should have the currentView as the only child view");
});

2 comments on commit 00b8940

@ppcano

This comment has been minimized.

Show comment
Hide comment
@ppcano

ppcano May 3, 2012

Contributor

@tomdale, perhaps, it could be useful to extend the feature to be able to pass an extended view. I have many view definitions like the one below:

Em.ContainerView.extend({
    childViews: ['child'],
    child: Em.View.extend({
         ....
    })
});
Contributor

ppcano replied May 3, 2012

@tomdale, perhaps, it could be useful to extend the feature to be able to pass an extended view. I have many view definitions like the one below:

Em.ContainerView.extend({
    childViews: ['child'],
    child: Em.View.extend({
         ....
    })
});
@tomdale

This comment has been minimized.

Show comment
Hide comment
@tomdale

tomdale May 6, 2012

Member

@ppcano Yep, we discussed doing that, as well as the ability to provide the currentView as a string.

Member

tomdale replied May 6, 2012

@ppcano Yep, we discussed doing that, as well as the ability to provide the currentView as a string.

Please sign in to comment.