2013-11-20 2 views
15

Я боролся с этим в течение последних нескольких часов, я делаю приложение ember для создания счета-фактуры. Я использую компонент ember (текстовое поле) для изменения полей с помощью клавиатуры, но поскольку действия не отправляются обратно на соответствующий контроллер, я не могу сохранить записи в focusOut или insertNewLine, и ничего не происходит. Я использую:Ember component sendAction() не работает

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

ответ

33

Вы должны определить, где будет посылаться при определении компонента в шаблоне.

{{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}} 
+1

Спасибо, связка, это решило мою проблему, я понимаю концепцию этого (компоненты являются автономными), но в моем случае это вводит повторение кода. – Wilhearts

+0

Вид может быть проще, если вы не заботитесь о том, чтобы быть автономным. – Kingpin2k

+0

Также обратите внимание, что цитаты в шаблоне ** действительно важны. – 0xcaff

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 изменять маршруты, даже если компонент не может быть кнопка/ссылка. Например, переход на изменение компонента, содержащего несколько входов выбора, или просто изменение маршрута изнутри компонента в целом.

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