Weird binding with Ember.Select value - ember.js

I'm having a weird issue with the Ember.Select view when I try to bind its value to a model.
Here is an abstract of what I'm doing, the complete jsbin can be found here:
Using JavaScript: http://jsbin.com/jayutuzazi/1/edit?html,js,output
Using CoffeeScript: http://jsbin.com/nutoxiravi/2/edit?html,js,output
Basically what I'm trying to do is use an attribute of a model to set an attribute of another model.
I have the Age model like this
App.Age = DS.Model.extend({
label: DS.attr('string'),
base: DS.attr('number')
});
And an other model named Person like this
App.Person = DS.Model.extend({
name: DS.attr('string'),
ageBase: DS.attr('number')
});
The template looks like this:
<!-- person/edit.hbs -->
<form>
<p>Name {{input value=model.name}}</p>
<p>
Age
{{view "select" value=model.ageBase
content=ages
optionValuePath="content.base"
optionLabelPath="content.label"}}
</p>
</form>
What I am trying to do is have a select in the Person edit form that lists the ages using base as value and label as label.
I expect the correct value to be selected when loading and to change when the selected option changes.
Has can be seen in the jsbin output, the selected is correctly populated but it sets the ageBase value of the edited person to undefined and does not select any option. The model value is correctly set when an option is selected though.
Am I doing something wrong ? Is it a bug ? What am I supposed to do to make this work ?
Thank you :)

You can conditionally render based on fulfilment of the ages as follows, since select doesn't handle promises (more on that below):
{{#if ages.isFulfilled}}
{{view "select" value=ageBase
content=ages
optionValuePath="content.base"
optionLabelPath="content.label"}}
{{/if}}
I updated your JsBin demonstrating it working.
I also illustrate in the JsBin how you don't have to qualify with model. in your templates since object controllers are proxies to the models they decorate. This means your view doesn't have to be concerned with if a property comes from the model or some computed property on the controller.
There is currently a PR #9468 for select views which I made a case for getting merged into Ember which addresses some issues with selection and option paths. There is also meta issue #5259 to deal with a number of select view issues including working with promises.
From issue #5259 you will find that Ember core developer, Robert Jackson, has some candidate select replacements. I cloned one into this JsBin running against latest production release version of Ember.
There is nothing at all preventing you using Roberts code as a select view replacement in your app. Asynchronous collections/promises will just work (and it is MUCH faster rendering from the benchmarks I have seen).
The template for that component is just:
{{#if prompt}}
<option disabled>{{prompt}}</option>
{{/if}}
{{#each option in resolvedOptions}}
<option {{bind-attr value=option.id}}>{{option.name}}</option>
{{/each}}
The js of the component is:
App.AsyncSelectComponent = Ember.Component.extend({
tagName: 'select',
prompt: null,
options: null,
initialValue: null,
resolvedOptions: null,
resolvedInitialValue: null,
init: function() {
var component = this;
this._super.apply(this, arguments);
Ember.RSVP.hash({
resolvedOptions: this.options,
resolvedInitialValue: this.initialValue
})
.then(function(resolvedHash){
Ember.setProperties(component, resolvedHash);
//Run after render to ensure the <option>s have rendered
Ember.run.schedule('afterRender', function() {
component.updateSelection();
});
});
},
updateSelection: function() {
var initialValue = Ember.get(this, 'resolvedInitialValue');
var options = Ember.get(this, 'resolvedOptions') || [];
var initialValueIndex = options.indexOf(initialValue);
var prompt = Ember.get(this, 'prompt');
this.$('option').prop('selected', false);
if (initialValueIndex > -1) {
this.$('option:eq(' + initialValueIndex + ')').prop('selected', true);
} else if (prompt) {
this.$('option:eq(0)').prop('selected', true);
}
},
change: function() {
this._changeSelection();
},
_changeSelection: function() {
var value = this._selectedValue();
this.sendAction('on-change', value);
},
_selectedValue: function() {
var offset = 0;
var selectedIndex = this.$()[0].selectedIndex;
if (this.prompt) { offset = 1; }
return Ember.get(this, 'resolvedOptions')[selectedIndex - offset];
}
});

The problem is that in:
{{view "select" value=model.ageBase
When the app starts, value is undefined and model.ageBase gets synchronized to that before value is synchronized to model.ageBase. So, the workaround is to skip that initial undefined value.
See: http://jsbin.com/rimuku/1/edit?html,js,console,output
The relevant parts are:
template
{{view "select" value=selectValue }}
controller
App.IndexController = Ember.Controller.extend({
updateModel: function() {
var value = this.get('selectValue');
var person = this.get('model');
if ( value ) { // skip initial undefined value
person.set('ageBase', value);
}
}.observes('selectValue'),
selectValue: function() {
// randomly used this one
return this.store.find('age', 3);
}.property()
});

givanse's answer should work.
I don't think it's because value is undefined, but because value is just an integer (42) and not equal to any of the selects content, which are Person objects ({ id: 2, label: 'middle', base: 42 }).
You could do something similar to what givens suggests or use relationships.
Models
//
// Models
//
App.Person = DS.Model.extend({
name: DS.attr('string'),
ageBase: DS.belongsTo('age', { async: true })
});
App.Age = DS.Model.extend({
label: DS.attr('string'),
base: DS.attr('number')
});
//
// Fixtures
//
App.Person.reopenClass({
FIXTURES: [
{ id: 1, name: 'John Doe', ageBase: 2 }
]
});
App.Age.reopenClass({
FIXTURES: [
{ id: 1, label: 'young', base: 2 },
{ id: 2, label: 'middle', base: 42 },
{ id: 3, label: 'old', base: 82 }
]
});
Template:
<h1>Edit</h1>
<pre>
name: {{model.name}}
age: {{model.ageBase.base}}
</pre>
<form>
<p>Name {{input value=model.name}}</p>
<p>
Age
{{view "select" value=model.ageBase
content=ages
optionValuePath="content"
optionLabelPath="content.label"}}
</p>
</form>

Ok, I found a solution that I think is more satisfying. As I thought the issue was coming from ages being a promise. The solution was to ensure that the ages list was loaded before the page was rendered.
Here is how I did it:
App.IndexRoute = Ember.Route.extend({
model: function() {
return Ember.RSVP.hash({
person: this.store.find('person', 1),
ages: this.store.findAll('age')
});
}
});
That's it! All I need from there is to change the view according the new model:
{{#with model}}
<form>
<p>Name {{input value=person.name}}</p>
<p>
Age
{{view "select" value=person.ageBase
content=ages
optionValuePath="content.base"
optionLabelPath="content.label"}}
</p>
</form>
{{/with}}
The complete working solution can be found here: http://jsbin.com/qeriyohacu/1/edit?html,js,output
Thanks again to #givanse and #Larsaronen for your answers :)

Related

EmberJS computed sort property conflicting with jQuery UI Sortable

I am having an issue with getting drag-and-drop sort functionality with EmberJS working.
The tutorials that cover this issue don't provide any help on the initial sort, which I am doing through a computed property.
What I'm encountering seems to be a race condition between ember's rerender when the sortedItems computed property changes and jQueryUI Sortable updating the DOM. List Items get duplicated, or disappear altogether upon sorting.
Route
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return Ember.Object.create({
id: 1,
title: "Title",
subtitle: "Subtitle",
items: [
Ember.Object.create({
name: "Item 2",
sortOrder: 2,
id: 1
}),
Ember.Object.create({
name: "Item 1",
sortOrder: 1,
id: 2
}),
Ember.Object.create({
name: "Item 3",
sortOrder: 3,
id: 3
})
]
});
}
});
Controller
import Ember from 'ember';
export default Ember.ObjectController.extend({
sortProperties: [ 'sortOrder' ],
sortedItems: Ember.computed.sort('model.items', 'sortProperties'),
actions: {
updateSortOrder: function(indexes) {
this.get('items').forEach(function(item) {
var index = indexes[item.get('id')];
item.set('sortOrder', index);
});
}
}
});
View
import Ember from 'ember';
export default Ember.View.extend({
didInsertElement: function() {
var controller = this.get('controller');
this.$(".item-list").sortable({
update: function(event, ui) {
var indexes = {};
$(this).find('li').each(function(index) {
indexes[$(this).data('id')] = index;
});
controller.send('updateSortOrder', indexes);
}
})
}
});
Template
<h1>{{ title }}</h1>
<h2>{{ subtitle }}</h2>
<ul class="item-list">
{{#each item in sortedItems }}
<li data-id="{{ unbound item.id }}">
name: {{ item.name }}<br />
sortOrder: {{ item.sortOrder }}<br />
id: {{ item.id }}
</li>
{{/each}}
</ul>
Here's a Barebones Ember app that reproduces the issue: https://github.com/silasjmatson/test-sortable
Question
Is there a way to avoid this race condition or sort only once when the controller is initialized?
Apologies if there is already an answer on the interwebs for this. I haven't been able to resolve this despite a week of searching/experimenting.
You can sort only once when the controller is initialised:
sortedItems: Ember.computed(function() {
return Ember.get(this, 'model.items').sortBy('sortOrder');
})
Because you're using the computed sort property it is attempting to sort the list for you whenever the sortOrder property changes on any item, which is rerendering the #each and doing something funky.
Just sort once initially using the method above and then let jQuery handle the order of items - rather than jQuery and Ember.

How to set Default Value in Ember js

Using Below code i have created Ember View.
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<div>
{{view "select" content=model prompt="Please select a name" selectionBinding="controllers.comboBox.model" optionValuePath="content.title" optionLabelPath="content.body" }}
</div>
<div>
{{view "select" content=model1 prompt="Please select a name" optionValuePath="content.title" optionLabelPath="content.title" }}
</div>
</script>
and App.Js
App = Ember.Application.create({
});
App.Router.map(function () {
});
App.IndexRoute = Ember.Route.extend({
model: function () {
return posts;
}
});
App.IndexController = Em.ArrayController.extend({
needs: ["comboBox"],
sendValueToServer: function () {
document.getElementById("comboval").value = this.get("controllers.comboBox.model.title");
}.observes("controllers.comboBox.model"),
model1: function () {
var valueq = this.get('controllers.comboBox.model.title');
console.log("value "+valueq);
return posts1;
}.property("controllers.comboBox.model")
});
App.ComboBoxController = Em.Controller.extend({
model: null,
});
App.ComboBox1Controller = Em.Controller.extend({
model1: null,
});
posts = [{
title: "Raja",
body: "There are lots of à la carte software environments in this world."
}, {
title: "Broken Promises",
body: "James Coglan wrote a lengthy article about Promises in node.js."
},
{
title: "Broken",
body: "James Coglan wrote a lengthy article about Promises in node.js."
}
];
posts1 = [{
title: "Raja",
body: "There are lots of à la carte software environments in this world."
}, {
title: "Broken Promises",
body: "James Coglan wrote a lengthy article about Promises in node.js."
},
{
title: "Broken",
body: "James Coglan wrote a lengthy article about Promises in node.js."
}
];
Above code using Prompt I was showing "Please select a name" Default Value.
but Initially i dont want Please select a name default value.
my requirement is need to show second value as a default value.
how can i do this.
In association to the question mentioned here,
Second dropdown not calling EveryTime Based on First drop down
To set a default value all it is required is to set a value to the bound property of the specific drop down.
http://emberjs.jsbin.com/loqivasova/1/edit
js
App.ComboBoxController = Em.Controller.extend({
model: posts[0],
});
if however it is required to also modify the second drop down based on this default value, then just add on("init") to the setComboBox1Model1 function,
js
setComboBox1Model1:function(){
var valueq = this.get('controllers.comboBox.model.title');
var valueFromPosts1 = posts1.findBy("title",valueq);
this.set("controllers.comboBox1.model1",valueFromPosts1?valueFromPosts1:null);
}.observes("controllers.comboBox.model").on("init")
http://emberjs.jsbin.com/jogaqinugi/1/edit?html,js,output
If it is required to set the value after the view has rendered, then you should use a view
js
App.IndexView = Em.View.extend({
setDefaulValue:function(){
this.set("controller.controllers.comboBox.model",posts[0]);
}.on("didInsertElement")
});
http://emberjs.jsbin.com/qugefipefi/1/edit?html,js,output

Display collection of elements, hide active element

UPDATE Since asking this question I have redesigned my UI such that I no longer need this feature; however I'm leaving this open and active for the sake of helping others who end up with a similar problem.
I'm listing a collection of elements inside a template and each element has a link that opens it up to the right of the list. When one is clicked, I want to hide just that element and show it again when another one is clicked. My current approach to doing this is to set an attribute (active) to true on the model. This feels wrong for three reasons:
This attribute is not actually part of the model's schema, it's just arbitrary; which makes it seem like a controller concern (see below for why that doesn't work)
I have to first set active to false on all models, forcing me to change another router's model, which may be good or bad, I'm not sure
In the recent PeepCode screencast he showed using #each.{attribute} to bind to an attributes in an array; this makes me feel like there must be something similar I could do (like this.set("#each.active", false)) to set them all in one fell swoop
I wanted to use a method on the controller but it doesn't seem I can pass arguments into functions in Handlebars if statements.
Here's the code I'm using to render the list:
{{#each note in controller}}
{{!v-- I was trying to do {{#if isCurrentNote note}} but that seems to be invalid handlebars}}
{{#unless note.active}}
<li class="sticky-list-item">
{{view Ember.TextArea classNames="sticky-note" valueBinding="note.content"}}
{{#linkTo note note classNames="sticky-permalink"}}
∞
{{/linkTo}}
</li>
{{/unless}}
{{/each}}
And here are the routes:
App.NotesController = Ember.ArrayController.extend({
// v-- this is what I was trying to do, but couldn't pass note in the template
isCurrentNote: function(note){
return this.get("currentNote") == note;
}.property("currentNote")
});
App.NoteRoute = Ember.Route.extend({
setupController: function(controller,model){
this.modelFor("notes").forEach(function(note){
note.set("active", false);
});
model.set("active", true);
}
});
Like I said, what I have works, but it feels wrong. Can anyone confirm my suspicion or help ease my soul a bit?
Thanks!
to me this looks like something that should be done mostly by the NotesView with a NotesController that stores the Note selection
Here is the fiddle: http://jsfiddle.net/colymba/UMkUL/6/
the NotesController would hold all the notes and a record of the selected one:
App.NotesController = Ember.ArrayController.extend({
content: [],
selectedNote: null,
selectNote: function(id){
var note = this.get('content').findProperty('id', id);
this.set('selectedNote', note);
}
});
with the NotesViewobserving that selection and showing/hiding elements of the list accordingly
App.NotesView = Ember.View.extend({
templateName: 'notes',
refresh: function(){
var view = this.$(),
selection = this.get('controller.selectedNote');
if (view) {
view.find('li').show();
if (selection) view.find('li.note_'+selection.id).hide();
}
}.observes('controller.selectedNote')
});
Here is the Note object and it's 2 templates (when in a list or displayed in full). The ListView handles the click event and passes the id to the NotesController.
App.Note = Ember.Object.extend({
name: '',
content: ''
});
App.NoteView = Ember.View.extend({
templateName: 'note'
});
App.NoteListItemView = Ember.View.extend({
tagName: 'li',
templateName: 'noteListItem',
classNameBindings: ['noteID'],
noteID: function(){
return 'note_' + this._context.id;
}.property(),
click: function(e){
this.get('controller').selectNote(this._context.id);
}
});
in the NotesView template everything is displayed and if there is a selectedNote, we display the Note again in full:
{{#each note in controller}}
{{#with note}}
{{view App.NoteListItemView}}
{{/with}}
{{/each}}
{{#if selectedNote}}
{{#with selectedNote}}
{{view App.NoteView}}
{{/with}}
{{/if}}
the Routes to put it together
App.Router.map(function() {
this.resource('notes', { path: "/notes" });
});
App.IndexRoute = Ember.Route.extend({
enter: function() {
this.transitionTo('notes');
}
});
App.NotesRoute = Ember.Route.extend({
model: function() {
return [
App.Note.create({id: 1, name: 'Milk', content: '15% fresh milk'}),
App.Note.create({id: 2, name: 'Juice', content: 'Orange with pulp'}),
App.Note.create({id: 3, name: 'Cereals', content: 'Kelloggs Froot Loops'}),
];
},
setupController: function(controller, model) {
controller.set('content', model);
},
renderTemplate: function(controller, model) {
this.render('notes', { outlet: 'content' });
}
});

createRecord called w/o params does not add object to collection

Using:
ember-1.0.0-pre.4.js
ember-data.js REVISION:11
handlebars-1.0.rc.2.js
Please have a look at this jsFiddle illustrating the described problem.
I have a list of items that are displayed in a template. The template contain a linkTo helper that let's the controller add an item to the collection and is shown as a text input on the page.
Adding the item to the collection is done by the controller:
App.TodoItem = DS.Model.extend({
title: DS.attr('string', { defaultValue: "unknown" })
});
App.Router.map(function () {
this.resource('todo_items')
});
App.TodoItemsRoute = Em.Route.extend({
model: function () {
return App.TodoItem.find();
}
});
App.TodoItemsController = Em.ArrayController.extend({
addTodoItem: function () {
App.TodoItem.createRecord();
}
});
If I want the new item to be shown is the list, I have to pass params to createRecord, otherwise the item is not visible. The same behaviour can be reproduced by using Chrome's inspector and then the item can be made visible as follows:
// Open the jsFiddle http://jsfiddle.net/bazzel/BkFYd/ and select 'result(fiddle.jshell.net) in the inspector, then:
var item = App.TodoItem.createRecord();
// Nothing visible yet.
item.set('title', 'Whatever');
// Now the text input appear with the title as its value.
Is this expected behaviour and if so, what am I missing here?
I took time to redo your example the way i feel things should be done properly with Emberjs. You should rather make sure of transaction and properly define your views and then all your issues get taken care of. So here's how i think you should do this
Define a view for the textfield to capture the value being entered or
just bind it to the model property.
Listing items and adding a new item to the list should be done in two different views and should not be mixed together
<script type="text/x-handlebars">
{{outlet}}
<div>
{{outlet 'addItem'}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="todo_items">
{{#linkTo 'todo_items.new'}}Add Todo Item{{/linkTo}}
<ul>
{{#each item in controller}}
<li>
{{#unless item.isNew}}
{{item.title}}
{{/unless}}
</li>
{{/each}}
</ul>
</script>
Define different states for listing items and adding a new one
To benefit from automatic binding of your text field value to the
model property, you need to associate an ObjectController to the TodoItemsNew route
Finally, make use of transaction to create and commit records to the store
window.App = Em.Application.create();
App.TodoItem = DS.Model.extend({
title: DS.attr('string')
});
App.TodoItem.FIXTURES = [{
id: 1,
title: 'Lorem'
}, {
id: 2,
title: 'Ipsum'
}];
App.store = DS.Store.create({
revision: 11,
adapter: DS.FixtureAdapter.create()
});
App.Router.map(function () {
this.resource('todo_items',function(){
this.route('new');
})
});
App.IndexRoute = Em.Route.extend({
redirect: function () {
this.transitionTo('todo_items');
}
});
App.TodoItemsRoute = Em.Route.extend({
model: function () {
return App.TodoItem.find();
}
});
App.TodoItemsNewRoute = Em.Route.extend({
transaction: App.store.transaction(),
setupController:function(controller) {
console.info(controller.toString());
controller.set('content',this.transaction.createRecord(App.TodoItem));
},
renderTemplate: function() {
this.render('addItem',{
into:'application',
outlet:'addItem',
})
},
events: {
addItem: function() {
this.transaction.commit();
this.transitionTo('todo_items');
}
}
});
App.TodoItemsController = Em.ArrayController.extend();
App.TodoItemsNewController = Em.ObjectController.extend();
App.TextField = Ember.TextField.extend({
insertNewline: function () {
this.get('controller').send('addItem')
}
});
Here' is a working version of the example on jsfiddle. Hopefully, i helped with this example clarify some of your issues.
Thank you Ken for answering my question. It indeed feels like a more proper of way of doing this in Ember. However, I still think it's difficult to get the hang of which objects are accessible from where...
Your example inspired me to do a rewrite of my code. I also made some changes to your approach:
I'm not sure if it's the best practice, my I don't create a store instance. Instead I define a Store class.
The content for the TodoItemsNewController is set by calling the model property on the corresponding route.
renderTemplate in the TodoItemsNewRoute only needs the outlet key.
<script type="text/x-handlebars">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="todo_items">
{{#linkTo 'todo_items.new'}}Add Todo Item{{/linkTo}}
<ul>
{{outlet "addItem"}}
{{#each controller}}
<li>
{{#unless isNew}}
{{title}}
{{/unless}}
</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="todo_items/new">
{{view Ember.TextField valueBinding="title" placeholder="Enter title"}}
window.App = Em.Application.create();
App.TodoItem = DS.Model.extend({
title: DS.attr('string', {
defaultValue: "unknown"
})
});
App.TodoItem.FIXTURES = [{
id: 1,
title: 'Lorem'
}, {
id: 2,
title: 'Ipsum'
}];
App.Store = DS.Store.extend({
revision: 11,
adapter: DS.FixtureAdapter.create()
});
App.Router.map(function() {
this.resource('todo_items', function() {
this.route('new');
});
});
App.IndexRoute = Em.Route.extend({
redirect: function() {
this.transitionTo('todo_items');
}
});
App.TodoItemsRoute = Em.Route.extend({
model: function() {
return App.TodoItem.find();
}
});
App.TodoItemsNewRoute = Em.Route.extend({
model: function() {
return App.TodoItem.createRecord();
},
renderTemplate: function() {
this.render({
outlet: 'addItem'
});
}
});
App.TodoItemsNewView = Em.View.extend({
tagName: 'li'
});
The updated example is on jsFiddle.
Any reviews are welcome.

select dropdown with ember

I'm trying to produce a select input and pass the selected object to the change event on the view. The ember contact example uses a <ul> but with a select the view needs to be outside the each otherwise the change even isn't fired.
Here is the view js:
App.SelectView = Ember.View.extend({
change: function(e) {
//event for select
var content = this.get('content');
console.log(content);
App.selectedWidgetController.set('content', [content]);
},
click: function(e) {
//event for ul
var content = this.get('content');
console.log(content);
App.selectedWidgetController.set('content', [content]);
}
});
The ul from the example works:
<ul>
{{#each App.widgetController.content}}
{{#view App.SelectView contentBinding="this"}}
<li>{{content.name}}</li>
{{/view}}
{{/each}}
</ul>
But if I replace html directly, the change event isn't fired (which makes sense)
<select>
{{#each App.widgetController.content}}
{{#view App.SelectView contentBinding="this"}}
<option>{{content.name}}</option>
{{/view}}
{{/each}}
</select>
So I guess the select has to be wrapped in the view.. in which case how do I pass the relevant object?... This code results in the entire array being passed:
{{#view App.select_view contentBinding="App.widgetController.content"}}
<select>
{{#each App.widgetController.content}}
<option>{{name}}</option>
{{/each}}
</select>
{{/view}}
Ember now has a built-in Select view.
Here's a usage example:
var App = Ember.Application.create();
App.Person = Ember.Object.extend({
id: null,
firstName: null,
lastName: null,
fullName: function() {
return this.get('firstName') + " " + this.get('lastName');
}.property('firstName', 'lastName').cacheable()
});
App.selectedPersonController = Ember.Object.create({
person: null
});
App.peopleController = Ember.ArrayController.create({
content: [
App.Person.create({id: 1, firstName: 'Yehuda', lastName: 'Katz'}),
App.Person.create({id: 2, firstName: 'Tom', lastName: 'Dale'}),
App.Person.create({id: 3, firstName: 'Peter', lastName: 'Wagenet'}),
App.Person.create({id: 4, firstName: 'Erik', lastName: 'Bryn'})
]
});
Your template would look like:
{{view Ember.Select
contentBinding="App.peopleController"
selectionBinding="App.selectedPersonController.person"
optionLabelPath="content.fullName"
optionValuePath="content.id"}}
Again, here's a jsFiddle example: http://jsfiddle.net/ebryn/zgLCr/
check out the answers to a similar question: How to bind value form input select to attribute in controller
In the examples a CollectionView is used with an tagName=select. You may find this helpful in getting it work.
EDIT: Since I was looking to implement a select myself, here is the solution I came up with:
views/form.js.hjs:
{{#view contentBinding="App.typeController" valueBinding="type" tagName="select"}}
{{#each content}}
<option {{bindAttr value="title"}}>{{title}}</option>
{{/each}}
{{/view}}
{{#view Ember.Button target="parentView" action="submitEntry"}}Save{{/view}}
The select is part of a form. I do check for the submit event and in there read the value:
app.js.coffee
# provides the select, add value: 'my_id' if you need differentiation
# between display name (title) and value
app.typeController = Ember.ArrayProxy.create
content: [{title:'Energy'}, {title:'Gas'}, {title:'Water'}]
# simplified version, but should prove the point
app.form_view = Ember.View.create
templateName: 'views_form'
type: null
submitEntry: () ->
console.log this.$().find(":selected").val()
Hope this helps.
This isn't an Answer, just a fix on the broken jsfiddle link.. Apparently jsfiddle has no love for ember :/ But JsBin does! http://jsbin.com/kuguf/1/edit