从组件访问存储
我有一个组件,当用户点击组件时,它添加一些值来存储,我尝试使用这种方式,但我得到一个错误:
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
推logging可以从组件中存储吗? 为什么我无法访问存储? 我的模型名称是“AxisModel”,应用程序名称空间是“OlapApp”
在component
,当你的应用程序启动时,商店不会像route
或controller
那样自动注入。 这是因为组件被认为是更孤立的。
下面的内容不被认为是最佳实践。 一个组件应该使用传递给它的数据,而不知道它的环境。 处理这种情况的最好方法是使用
sendAction
来sendAction
你想要做的事情,并用控制器本身的store
来处理这个动作。
@ sly7_7build议是一个很好的build议,如果你有很多组件需要访问商店,那么这可能是一个很好的方法。
另一种到达store
可能是将store
周围的controller
所参考的store
。 在这种情况下,哪个controller
是无关紧要的,因为每个controller
都已经注入了对该store
的引用。 所以现在到达你的store
可以通过获取component
的targetObject
这将是围绕component
的controller
,然后获得store
。
例:
OlapApp.MeasureListItemComponent = Ember.Component.extend({ ... actions: { add: function(measure) { var store = this.get('targetObject.store'); ... } } });
在这里看到一个工作的例子。
希望能帮助到你。
更新回应你的评论有嵌套的组件
例如,如果您的子组件只嵌套一个级别,那么您仍然可以使用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')); } });
更新的例子 。
从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() });
目前的做法似乎是使用初始值设定项。 非常类似于@ 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 };
我相信这会将商店添加到所有组件中。
自Ember 2.1.0以来
export default Ember.Component.extend({ store: Ember.inject.service('store'), });
在Ember 2.1.0之前 – dependency injection的方式
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" }}
将属性传递给组件logging在这里
我不知道组件是否打算以这种方式使用。 但是,如果你想要的话,我想你可以声明一个初始化器,并将商店注入到所有组件中。
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
商店可以注入dependency injection的帮助。
例
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'); }, });
还没有人提到的另一种方法是简单地将controller.store传递给组件
{{my-awesome-component store=controller.store}}