Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind value form input select to attribute in controller

Tags:

ember.js

I try to bind value from input select to attribute "selectedValue" in controller.

This is app.js

Food = Ember.Application.create();

Food.appsController = Ember.Object.create({
  selectedValue: ""
});

Food.Todo = Ember.Object.extend({
  title: null,
  value: null
});

Food.FoodController = Ember.ArrayProxy.create({
  content: []
});

Food.FoodController.pushObject(Food.Todo.create({title:"a", value:"1"}));
Food.FoodController.pushObject(Food.Todo.create({title:"b", value:"2"}));
Food.FoodController.pushObject(Food.Todo.create({title:"c", value:"3"}));

This is index.html

{{#collection
    contentBinding="Todos.todosController"
    tagName="select"
    itemClassBinding="content.isDone"}}
  {{content.title}}
{{/collection}}

Output look like this

<select id="ember180" class="ember-view">
  <option id="ember192" class="ember-view">
    <script id="metamorph-0-start" type="text/x-placeholder"></script>
    a
    <script id="metamorph-0-end" type="text/x-placeholder"></script>
  </option>
  <option id="ember196" class="ember-view">
    <script id="metamorph-1-start" type="text/x-placeholder"></script>
    b
    <script id="metamorph-1-end" type="text/x-placeholder"></script>
  </option>
  <option id="ember200" class="ember-view">
    <script id="metamorph-2-start" type="text/x-placeholder"></script>
    c
    <script id="metamorph-2-end" type="text/x-placeholder"></script>
  </option>
</select>

I have no idea how to add value to option and how to binding selected value back to controller. Is this possible to do in Emberjs?

like image 569
Bank Avatar asked Dec 16 '11 08:12

Bank


3 Answers

Ember now has a built-in Select view.

You can find it in the latest Ember.js build here: http://cloud.github.com/downloads/emberjs/ember.js/ember-latest.js

Here's an example usage:

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/

like image 129
ebryn Avatar answered Nov 04 '22 11:11

ebryn


Jumping off from the solution for @pangrantz, this Fiddle example (http://jsfiddle.net/bsyjr/) illustrates some improvements: The Handlebars code is cleaner through the use of tagName. When tagName is set to "select", the child views automatically become "option" elements. See the Ember.CollectionView.CONTAINER_MAP in https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/views/collection_view.js to understand why. On the Javascript side, by specifying an itemViewClass, we can add the value attribute to the option element.

<script type="text/x-handlebars" >
    {{#collection Food.SelectView tagName="select" contentBinding="Food.foodController"
        valueBinding="Food.appsController.selectedValue"}}
      {{content.title}}
    {{/collection}}

    selected: {{view Ember.TextField valueBinding="Food.appsController.selectedValue"}}{{Food.appsController.selectedValue}}
</script>

Food = Ember.Application.create();

Food.SelectView = Ember.CollectionView.extend({
    value: null,
    itemViewClass: SC.View.extend({
        attributeBindings:['value'],
        valueBinding: 'content.value'
    }),

    valueChanged: function(){
        this.$().val( this.get('value') );
    }.observes('value'),

    didInsertElement: function(){
        var self = this;
        this.$().change(function(){
            var val = $('select option:selected').val();
            self.set('value', val);
        });
    }
});

Food.appsController = Ember.Object.create({
  selectedValue: ""
});

Food.Todo = Ember.Object.extend({
  title: null,
  value: null
});

Food.foodController = Ember.ArrayProxy.create({
  content: []
});

Food.foodController.pushObject(Food.Todo.create({title:"a", value:"1"}));
Food.foodController.pushObject(Food.Todo.create({title:"b", value:"2"}));
Food.foodController.pushObject(Food.Todo.create({title:"c", value:"3"}));

There is still room for improvement in the event handling, which is not using Ember's event framework, and it would make a lot of sense to use a custom written SelectView that doesn't leverage Handlebars, since IMO, it is dubious how much value Handlebars adds in this case.

like image 5
Luke Melia Avatar answered Nov 04 '22 10:11

Luke Melia


Using a custom Ember.View works for me, but I think there is a better solution...

See working example is this fiddle http://jsfiddle.net/pangratz/hcxrJ/

Handlebars:

{{#view Food.SelectView contentBinding="Food.foodController"
    valueBinding="Food.appsController.selectedValue"}}
    <select>
        {{#each content}}
            <option {{bindAttr value="value"}} >{{title}}</option>
        {{/each}}
    </select>
{{/view}}

app.js:

Food = Ember.Application.create();

Food.SelectView = Ember.View.extend({
    value: null,

    valueChanged: function(){
        this.$('select').val( this.get('value') );
    }.observes('value'),

    didInsertElement: function(){
        var self = this;
        this.$('select').change(function(){
            var val = $('select option:selected').val();
            self.set('value', val);
        });
    }
});

Food.appsController = Ember.Object.create({
  selectedValue: ""
});

Food.Todo = Ember.Object.extend({
  title: null,
  value: null
});

Food.foodController = Ember.ArrayProxy.create({
  content: []
});

Food.foodController.pushObject(Food.Todo.create({title:"a", value:"1"}));
Food.foodController.pushObject(Food.Todo.create({title:"b", value:"2"}));
Food.foodController.pushObject(Food.Todo.create({title:"c", value:"3"}));
like image 4
pangratz Avatar answered Nov 04 '22 09:11

pangratz