web-dev-qa-db-ja.com

コンポーネントからストアにアクセスする

コンポーネントがあり、ユーザーがコンポーネントをクリックすると、格納する値が追加されます。この方法を使用しようとしましたが、エラーが発生しました。

OlapApp.MeasureListItemComponent = Ember.Component.extend({
  tagName: 'li',
  isDisabled: false,
  attributeBindings: ['isDisabled:disabled'],
  classBindings: ['isDisabled:MeasureListItemDisabled'],

  actions: {
    add: function(measure) {
      var store = this.get('store');
      store.Push('OlapApp.AxisModel', {
            uniqueName: measure.uniqueName,
            name: measure.name,
            hierarchyUniqueName: measure.hierarchyUniqueName,
            type: 'row',
            isMeasure: true,
            orderId: 1
      });
    }
  }
});

これはエラーです:

Uncaught TypeError: Cannot call method 'Push' of undefined  MeasureListItemComponent.js:18

コンポーネントから保存するレコードをプッシュすることは可能ですか?なぜストアにアクセスできないのですか?私のモデル名は「AxisModel」で、アプリケーションの名前空間は「OlapApp」です

49
MBehtemam

componentでは、アプリの起動時にroutecontrollerのようにストアが自動的に挿入されません。これは、コンポーネントがより分離されていると考えられるためです。

以下は、ベストプラクティスとは見なされません。コンポーネントは、渡されたデータを使用する必要があり、その環境を認識しないでください。このケースを処理する最良の方法は、sendActionを使用して実行したいことをバブルアップし、コントローラー自体でstoreを使用してアクションを処理することです。

@ sly7_7の提案は良い提案であり、ストアにアクセスする必要がある場所から多くのコンポーネントがある場合、それはそれを行うための良い方法かもしれません。

storeにアクセスする別の方法は、storeが参照しているcomponentを囲むcontrollerを取得することです。この場合、すべてのcontrollerにすでにcontrollerが参照されているため、これはどのstoreでも関係ありません。したがって、storeを取得するには、componenttargetObjectを取得します。これは、controllerを囲むcomponentです。 storeを取得します。

例:

OlapApp.MeasureListItemComponent = Ember.Component.extend({
  ...
  actions: {
    add: function(measure) {
      var store = this.get('targetObject.store');
      ...
    }
  }
});

実際の例については、 here を参照してください。

それが役に立てば幸い。

ネストされたコンポーネントがあるコメントに応じて更新する

たとえば、子コンポーネントが1レベルだけネストされている場合、parentViewを使用して親のtargetObjectを参照できます。

App.ChildCompComponent = Ember.Component.extend({
  storeName: '',
  didInsertElement: function() {
    console.log(this.get('parentView.targetObject.store'));
    this.set('storeName', this.get('parentView.targetObject.store'));
  }
});

を更新しました。

43
intuitivepixel

Ember v1.10であるため、イニシャライザーを使用してストアをコンポーネントにインジェクトでき​​ます。参照: http://emberjs.com/blog/2015/02/07/ember-1 -10-0-released.html#toc_injected-properties

export default Ember.Component.extend({
    store: Ember.inject.service()
});
44

以来Ember 2.1.0

export default Ember.Component.extend({
  store: Ember.inject.service('store'),
});

before Ember 2.1.0-依存性注入方法

App.MyComponent = Ember.Component.extend({

  store: Ember.computed(function() {
     return this.get('container').lookup('store:main');
  })

});

before Ember 2.1.0-コントローラーウェイ

コントローラからストアをプロパティとして渡すことができます:

App.MyComponent = Ember.Component.extend({

  value: null,
  store: null,
  tagName: "input",

  didInsertElement: function () {

     if (!this.get('store')) {
        throw 'MyComponent requires store for autocomplete feature. Inject as store=store'
     }
  }

});

ストアは各コントローラーで利用できます。そのため、親ビューでは、次のようにコンポーネントを含めることができます。

{{view App.MyComponent
    store=store
    class="some-class"
    elementId="some-id"
    valueBinding="someValue"
}}

コンポーネントへのプロパティの受け渡しは文書化されています here

14
Jan Míšek

これを行う現在のember-cliの方法は、イニシャライザーを使用しているようです。 @ Sly7_7回答に非常に似ています。

基本的なモデルを使用するには:

  ember g initializer component-store-injector

次に、これを編集して:

// app/initializers/component-store-injector.js

export function initialize(container, application) {
  application.inject('component', 'store', 'store:main');
}

export default {
  name: 'component-store-injector',
  initialize: initialize
};

これにより、すべてのコンポーネントにストアが追加されると考えています。

https://github.com/ember-cli/ember-cli-todos から盗まれた

13
jomofrodo

コンポーネントがそのような方法で使用されることを意図しているかどうかはわかりません。ただし、必要に応じて、イニシャライザを宣言し、ストアをすべてのコンポーネントに注入できると思います。

Ember.onLoad('OlaApp', function(OlaApp) {
  OlapApp.initializer({
    name: 'injectStoreIntoComponents',
    before: 'registerComponents',
    initialize: function(container, application){
      container.register('store:main', App.Store);
      container.injection('component', 'store', 'store:main');
    }
  })
});

以下は、不自然だが実際の例です。 http://jsbin.com/AlIyUDo/6/edit

7
sly7_7

ストアは、依存性注入を使用して注入できます。

import Ember from 'ember';

export default Ember.Component.extend({

  /**
   *
   */
  store: Ember.inject.service(),

  /**
   * Initialize the component.
   */
  init() {
    this.initialize();

    this._super();
  },

  /**
   * Initialize the properties and prerequisites.
   */
  initialize() {
    // Set the component properties
    this.todos().then((data) => {
      this.set('todoEntries', data);
    });
  },

  /**
   * Returns the todo entries.
   *
   * @returns {*|Promise|Promise.<T>}
   */
  todos() {
    const store = this.get('store');

    return store.findAll('todo');
  },

});
6
user634545

誰もまだ言及していない別の方法は、controller.storeをコンポーネントに単に渡すことです。

{{my-awesome-component store=controller.store}}
4
TrevTheDev