Ember: Select views by type field
See http://discuss.emberjs.com/t/how-to-render-a-view-when-its-class-varies-based-on-model-attributes/833
HTML
<script src="https://s3.amazonaws.com/kiddsoftware-jsfiddle/handlebars-1.0.0-rc.3.js"></script>
<script src="https://s3.amazonaws.com/kiddsoftware-jsfiddle/ember-1.0.0-rc.2.js"></script>
<script src="https://s3.amazonaws.com/kiddsoftware-jsfiddle/ember-data-a29070da.js"></script>
<script type="text/x-handlebars">
<h1>Ember: Select views by type field</h1>
{{view Ember.TextField type="number"}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{#each controller}}
{{view App.WidgetView}}
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="widget">
<h2>{{name}}</h2>
<div class="content">
<!-- This is the magic bit. -->
{{view view.subViewType}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="loading">
<p>Loading your widget...</p>
</script>
<script type="text/x-handlebars" data-template-name="weather">
<p>Weather map goes here.</p>
</script>
<script type="text/x-handlebars" data-template-name="scores">
<p>Sports scores go here.</p>
</script>
CSS
.widget {
float: left;
width: 40%;
border: 1px solid black;
background: #ccf;
margin-right: 10px;
}
.widget h2 {
margin: 0 0 10px 0;
padding: 10px;
border-bottom: 1px solid black;
font-size: 14px;
}
.widget .content {
padding: 0 10px;
}
JavaScript
window.App = Ember.Application.create();
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.FixtureAdapter.create()
});
App.Widget = DS.Model.extend({
type: DS.attr("string"),
name: DS.attr("string")
});
App.Widget.FIXTURES = [{
id: 1,
name: "Local Weather",
type: "weather"
}, {
id: 2,
name: "Sports Scores",
type: "scores"
}];
App.IndexRoute = Ember.Route.extend({
model: function () {
return App.Widget.find();
}
});
App.WidgetView = Ember.View.extend({
templateName: "widget",
classNames: ["widget"],
// Choose what kind of view we want to use to render this widget.
// This gets used by our template.
subViewType: function () {
switch (this.get("context.type")) {
case "weather": return App.WeatherView;
case "scores": return App.ScoresView;
default: return App.LoadingView;
}
}.property("context.type"),
// We need to trigger this rerender manually when subViewType
// changes, because Handlebars {{view ...}} isn't smart enough.
subViewTypeDidChange: function () {
this.rerender();
}.observes("subViewType")
});
App.LoadingView = Ember.View.extend({
templateName: "loading"
});
App.WeatherView = Ember.View.extend({
templateName: "weather"
});
App.ScoresView = Ember.View.extend({
templateName: "scores"
});
// Uncomment this to see what happens when a widget's type changes.
// Of course, in practice, you'd go from null -> a real type when
// the object loads, and not from a real type -> null. But it's
// enough to prove that everything works.
//setTimeout(function () {
// widget = App.Widget.find(2);
// console.log("Updating", widget);
// widget.set("type", null);
//}, 3000);