Подтвердить что ты не робот

Доступ к хранилищу от компонента

У меня есть компонент, и когда пользователь нажимает на компонент, он добавляет некоторое значение для хранения, я пытаюсь использовать этот способ, но я получаю сообщение об ошибке:

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"

4b9b3361

Ответ 1

В component хранилище не вводится автоматически, как в route или controller, когда ваше приложение запускается. Это связано с тем, что компоненты считаются более изолированными.

То, что следует ниже, не считается лучшей практикой. Компонент должен использовать данные, переданные в него, и не знать об этой среде. Лучший способ справиться с этим случаем - использовать sendAction для создания пузырьков, что вы хотите сделать, и обработать действие с помощью store в самом контроллере.

@sly7_7 предложение хорошее, и если у вас есть много компонентов, откуда вам нужен доступ к магазину, тогда это может быть хорошим способом сделать это.

Другим подходом к вашему store может стать обращение к store к вашей component окружению controller. В этом случае не имеет значения, что controller это потому, что каждый controller уже ссылается на store, введенный в него. Итак, теперь, чтобы добраться до вашего store, можно сделать, получив component targetObject, который будет controller, окружающий component, а затем получите store.

Пример:

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

См. здесь для рабочего примера.

Надеюсь, что это поможет.

Обновление в ответ на ваш комментарий с вложенными компонентами

Если, например, ваш дочерний компонент является только вложенным на один уровень, вы все равно можете обратиться к родительскому объекту targetObject с помощью parentView:

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

Обновлен пример.

Ответ 3

Текущий способ 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

Ответ 4

Так как Ember 2.1.0

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

до Ember 2.1.0 - путь инъекции зависимостей

App.MyComponent = Ember.Component.extend({

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

});

до 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"
}}

Передача свойств компоненту документируется здесь

Ответ 5

Я не знаю, должны ли компоненты использоваться таким образом. Но если вы хотите, я думаю, вы можете объявить инициализатор и ввести хранилище во все компоненты.

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

Ответ 6

Магазин можно вводить с помощью инъекции зависимостей.

Пример

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');
  },

});

Ответ 7

Другим способом, о котором еще никто не упомянул, является просто передать controller.store на компонент, например.

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