2011-12-16 3 views
7

Я пытаюсь привязать значение от ввода, чтобы выбрать атрибут «selectedValue» в контроллере.Как связать ввод формы формы выберите атрибут в контроллере

Это 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"})); 

Это index.html

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

Выходной взгляд, как этот

<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> 

Я понятия не имею, как добавить значение для опции и как привязать выбранное значение к контроллеру. Это можно сделать в Emberjs?

ответ

7

У Ember теперь есть встроенный Select view.

Вы можете найти его в последней версии Ember.JS построить здесь: http://cloud.github.com/downloads/emberjs/ember.js/ember-latest.js

Вот пример использования:

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'}) 
    ] 
}); 

Ваш шаблон будет выглядеть следующим образом:

{{view Ember.Select 
     contentBinding="App.peopleController" 
     selectionBinding="App.selectedPersonController.person" 
     optionLabelPath="content.fullName" 
     optionValuePath="content.id"}} 

Снова, вот пример jsFiddle: http://jsfiddle.net/ebryn/zgLCr/

+0

должен добавить этот вид в ядро ​​Ember :-) – Bank

+1

У меня есть улучшенная версия, которая скоро будет включена в Ember: https://github.com/emberjs/ember.js/pull/424 – ebryn

+0

Кстати, это [Ember.Select api] (http://emberjs.com/api/classes/Ember.Select.html) –

4

Использование пользовательских Ember.View работают для меня, но я думаю, что есть лучшее решение ...

Смотрите пример работает в этой скрипке http://jsfiddle.net/pangratz/hcxrJ/

: Рули

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

приложения .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"})); 
+0

Это решение работает хорошо me по нескольким причинам: a) Вид Ember.Select возвращает весь объект в массиве содержимого в качестве выбранного значения, в то время как я o чтобы получить фактическое значение выбора. b) Для того, что я работаю над этой реализацией, происходит намного быстрее: мне не нужны привязки на ярлыках и значениях, они не меняются (я удалил метод valueChanged в расширении класса представления выше, так как не сделал это необходимо) Заключительное замечание: метод select change handler содержит небольшую ошибку (когда у вас есть несколько селекторов): $ ('select options ... должен быть self. $ (' select options ... – Visionscaper

5

Спрыгнув с решения для @pangrantz, этот Fidd Пример (http://jsfiddle.net/bsyjr/) иллюстрирует некоторые улучшения: код Handlebars является более чистым с помощью tagName. Когда tagName установлен в «select», дочерние представления автоматически становятся элементами «option». См. Ember.CollectionView.CONTAINER_MAP в https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/views/collection_view.js, чтобы понять, почему. На стороне Javascript, указав itemViewClass, мы можем добавить атрибут value в элемент option.

<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"})); 

Существует еще место для улучшения обработки, которая не используют рамки событий Ember мероприятия, и это сделало бы много смысла использовать пользовательское письменное SelectView, не LEVERAGE рулей, так как ИМО, сомнительно, сколько добавляет Handlebars в этом случае.

+3

Стоит отметить, что хелпер '{{#collection}}' устарел, так как одни и те же результаты могут быть достигнуты с большей ясностью, используя '{{#each}}' как @pangratz. –

+0

Чтобы дать дополнительные разъяснения, все еще есть места, где '{ {#collection}} '. Но сначала я попытаюсь использовать' {{#each}} ', и если вы не сможете получить нужные результаты, тогда рассмотрите' {{#collection}} 'мы планируем для дальнейшего улучшения '{{#each}}', который будет охватывать больше c асы. –

1

Я не уверен, что это полезно для других, но я делал что-то подобное на основе ответов здесь, и сделал этот SelectView, который должен работать и в этом контексте. Он привязывается к «изменению», выполняет выбранное в данный момент представление и затем делает что-то с его содержимым.

Food.SelectView = Ember.CollectionView.extend({ 
    change: function(e) { 
    var selected = this.$().find(":selected").index(); 
    var content = this.get('childViews')[selected].content; 
    // Do something with the result 
    Food.appsController.set('selectedValue', content.title); 
    } 
}); 

Таким образом, вы можете обходить объект, а не индекс выбора.

Смежные вопросы