【问题标题】:Ember component sendAction() not workingEmber 组件 sendAction() 不起作用
【发布时间】:2013-12-05 04:19:36
【问题描述】:

过去几个小时我一直在努力解决这个问题,我正在制作一个用于创建发票的 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')
});

项目控制器

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

【问题讨论】:

    标签: javascript ember.js ember-data


    【解决方案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 方法来更改路由,即使该组件可能不是按钮/链接。例如,导航包含多个选择输入的组件的更改,或者只是从一个组件内更改路由。

    【讨论】:

      猜你喜欢
      • 2014-11-07
      • 2017-02-15
      • 1970-01-01
      • 1970-01-01
      • 2015-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多