web-dev-qa-db-ja.com

Emberコンポーネント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);
16
Wilhearts

テンプレートでコンポーネントを定義するときに、アクションの送信先を定義する必要があります。

{{edit-item value=desc createItem='someactionoutside'}}

これは、アクションの名前が場所によって異なる場合です(これはコンポーネントであるため、場所によって意味が異なる可能性があります)。また、アクションの衝突/トリガーされたアクションを回避します。コンポーネントのインスタンスを2つ持つというアイデアを考えてみてください。それぞれが、コントローラーで異なるアクションをトリガーする必要があります。

{{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}}
34
Kingpin2k

@ Kingpin2kによるNiceの回答に加えて、アクションの名前が常に同じであり、コンポーネントを含める構文を単純化したい場合は、コンポーネント内でアクションの名前を定義することもできます。すなわち。

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メソッドを使用してルートを変更します。たとえば、複数の選択入力を含むコンポーネントの変更をナビゲートしたり、一般的にコンポーネント内からルートを変更したりします。

2
genkilabs