Углеродный компонент sendAction() не работает
Я боролся с этим в течение последних нескольких часов, я делаю ember-приложение для создания счета-фактуры. Я использую компонент ember (текстовое поле) для изменения полей с помощью клавиатуры, но поскольку действия не отправляются обратно на соответствующий контроллер, я не могу сохранить записи в focusOut или insertNewLine, и ничего не происходит. Я использую:
Ember : 1.1.2
Ember Data : 1.0.0-beta.3
Handlebars : 1.0.0
jQuery : 1.9.1
это должно выглядеть следующим образом: https://dl.dropboxusercontent.com/u/7311507/embercomponent.png
Проблема, кажется, лежит либо в контроллере, либо в компоненте, кажется, что я что-то пропустил.
функция console.log вызывается в компоненте, вызов sendAction никогда не работает...
Спасибо за помощь.
ItemsRoute
App.ItemsRoute = Ember.Route.extend({
renderTemplate: function() {
// Render default outlet
this.render();
// render extra outlets
this.render("client", { outlet: "client", into: "application"});
},
model: function() {
return this.store.find('item');
}
});
ItemsController
App.ItemsController = Em.ArrayController.extend({
actions: {
createItem: function () { // NEVER GETS CALLED FROM COMPONENT
var title = "Nouvel élément"
// Create the new Todo model
var item = this.store.createRecord('item', {
desc: title,
qty: 1,
price: 0
});
// Save the new model
item.save();
}
},
totalCount: function(){
var total = 0;
this.get('model').forEach(function(item){
total += item.get('totalprice');
});
return total;
}.property('@each.qty', '@each.price')
});
ItemController
App.ItemController = Em.ObjectController.extend({
didInsertElement: function(){
this.$().focus();
},
actions: {
testAction: function(){ // NEVER GETS CALLED FROM COMPONENT
console.log("controller recieved call for testAction");
},
saveItem: function(value) {
this.get('model').save();
},
removeItem: function() {
var item = this.get('model');
item.deleteRecord();
item.save();
},
},
isHovering: false
});
Шаблон элементов
<script type="text/x-handlebars" data-template-name="items">
<!-- ... -->
<tbody>
{{#each itemController="item"}}
{{view App.ItemView }}
{{/each}}
</tbody>
<!-- ... -->
</script>
Шаблон ItemView
<script type="text/x-handlebars" data-template-name="item">
<td class="desc">{{edit-item value=desc}}</td>
<td class="qty">{{edit-item-number value=qty }}</td>
<td class="">{{edit-item-number step="25" value=price}}</td>
<td class="totalprice">
{{ totalprice }}
<div class="delete-item" {{bindAttr class="isHovering"}} {{action "removeItem" on="click"}}>
<i class="icon-trash"></i>
</div>
</td>
</script>
Представления/Компоненты
App.ItemView = Em.View.extend({
templateName: "item",
tagName: "tr",
mouseEnter: function(event) {
this.get('controller').set('isHovering', true);
},
mouseLeave: function(event) {
this.get('controller').set('isHovering', false);
}
});
App.EditItem = Em.TextField.extend({
becomeFocused: function() {
this.$().focus();
}.on('didInsertElement'),
insertNewline: function(){
console.log('Tried to insert a new line'); // WORKS
this.triggerAction('createItem'); // DOESN'T WORK
},
focusOut: function(){
console.log('Focused the Field Out') // WORKS
this.triggerAction('testAction', this); // DOESN'T WORK
}
});
App.EditItemNumber = App.EditItem.extend({
becomeFocused: null,
attributeBindings: ["min", "max", "step"],
type: "number",
min: "0"
});
Ember.Handlebars.helper('edit-item', App.EditItem);
Ember.Handlebars.helper('edit-item-number', App.EditItemNumber);
Ответы
Ответ 1
Вы должны определить, куда будет отправлено действие при определении компонента в шаблоне.
{{edit-item value=desc createItem='someactionoutside'}}
это в случае, если действие имеет другое имя в разных местах (так как это компонент, он может иметь разные значения в разных местах). Он также избегает конфликтов действий/инициированных действий. Подумайте об идее наличия двух экземпляров компонента, и каждый из них должен инициировать другое действие в контроллере
{{edit-item value=desc createItem='createUser'}}
{{edit-item value=desc createItem='createShoppingCart'}}
в вашем случае вы можете просто написать
{{edit-item value=desc createItem='createItem'}}
И внутри вашего компонента вы вызываете
this.sendAction('createItem', param1, param2, ....);
Если вы не заботитесь о том, чтобы быть автономным, как компонент, вы можете просто использовать представление, а не компонент. Вы можете зарегистрировать его как помощника, и он будет выглядеть так же красиво.
Em.Handlebars.helper('edit-item', Em.View.extend({
templateName: 'some_template',
actions: function(){
// etc etc
}
}));
{{edit-item}}
Ответ 2
В дополнение к приятному ответу @Kingpin2k вы также можете определить свое имя действия в компоненте, если оно всегда одно и то же, и вы хотите упростить синтаксис включения вашего компонента. то есть.
import Ember from 'ember';
export default Ember.Component.extend(SchoolPlayerProspectMixin, {
//Here we define an attribute for a string that will always be the same
transitionToRoute: "transitionToRoute",
somethingChanged: function(){
console.log( "OMG something changed, lets look at a post about it!" );
//Here we are passing our constant-attribute to the sendAction.
self.sendAction('transitionToRoute', "post.show", post );
}.observes('changableThing'),
});
В этом примере компонент использует метод transitionToRoute родительских контроллеров для изменения маршрутов, даже если компонент не может быть кнопкой/ссылкой. Например, переход на изменение компонента, содержащего несколько входов выбора, или просто изменение маршрута изнутри компонента в целом.