如何将商店注入组件(使用localstorage适配器时)

时间:2015-02-03 17:33:36

标签: ember.js

Ember docs说要定义这样的商店

MyApp.Store = DS.Store.extend();

如果您在组件中查找记录,这个doc表示您可以将商店注入到这样的组件中

// inject the store into all components
App.inject('component', 'store', 'store:main');

但是,我正在使用我定义的本地存储适配器

App.ApplicationAdapter = DS.LSAdapter.extend({           命名空间:'my-namespace'     });

因此,我不知道如何按照上述说明将其注入组件(我需要查找记录)。

按照this SO answer的说明,我尝试将store注入组件,方法是将其引入store=store和/或store=controller.store

<li> {{my-component id=item.customid data=item.stats notes=item.notes store=store}} </li>

<li> {{my-component id=item.customid data=item.stats notes=item.notes store=controller.store}} </li>

然后我们的目标是能够在组件

中执行此操作
      var todo = this.get('store');
      console.log(todo, "the new store");
      todo.set('notes', bufferedTitle);
      console.log(todo, "todo with notes set");
      todo.save();

但是,todo.save();始终会触发

Uncaught TypeError: undefined is not a function

请注意我登录了商店?这就是它显示的内容

Class {_backburner: Backburner, typeMaps: Object, recordArrayManager: Class, _pendingSave: Array[0], _pendingFetch: ember$data$lib$system$map$$Map…}

如果我检查它(通过打开这里没有显示的树),它确实表明注释是通过todo.set('notes', bufferedTitle);设置的,但它没有我的模型的任何其他属性我为索引路由定义的,这个对象没有'save'方法。因此,它似乎不是实际的商店,而只是一些反叛者的对象。

我尝试this SO answer得到了相同的结果,它说要获取targetObject的存储

var todo = this.get('targetObject.store');

注意,我也试过这个,即将商店设置为商品的商店。

 <li> {{my-component id=item.customid data=item.stats notes=item.notes store=item.store}} </li>

应该注意的是,如果我在组件中设置商店,我可以通过执行{{store}}来打印页面上的商店

<DS.Store:ember480>

但即使在应用程序代码中,我也无法在处理点击的操作中执行var todo = this.get('store');

问题,使用localStorage适配器,我如何在组件中查找记录(目的是能够更改记录然后再次保存)

注意,如果这很重要,我会像这样定义(索引)路线的模型

App.Index = DS.Model.extend({

        title: DS.attr('string'),

版本(遗憾的是我不知道Ember数据的版本或我正在使用的适配器)

Ember Inspector
1.7.0
Ember
1.9.1
Ember Data
<%= versionStamp %>
Handlebars
2.0.0
jQuery
1.10.2

响应更多信息请求进行更新

设置问题的代码非常简单。 这是路由器(资源名称不好:)     App.Router.map(函数(){      this.resource('index',{path:'/'});     }

以下是获取在路径

中使用记录的路线
App.IndexRoute = Ember.Route.extend({
      model: function{
      var resource = this.store.find('index');
       return resource;
       }
     });

我有一个索引控制器,它对组件没有任何作用(除非我应该在Controller上定义由组件事件触发的方法)

在html中,我使用把手将数据传递给组件

   {{#each item in items}}
 <li> {{my-component id=item.customid data=item.stats notes=item.notes store=store}}                   
   {{/each}}

然后,在components/my-component中,我有一个标签,当点击时应该触发一个动作,让我编辑模型上的一个属性

<label> {{action "editTodo" on="doubleClick">{{notes}}</label>

该点击会在App.MyComponent中触发此代码,从而触发提示此问题的错误

 var todo = this.get('store')
 todo.set('notes', bufferedTitle);
 todo.save()

4 个答案:

答案 0 :(得分:14)

IMHO将store注入组件并不是最好的想法......通过设计,组件应该是隔离的,不应该对store有任何了解。

在您提供的文档中,它已经写了:通常,直接在组件中查找模型是一种反模式,您应该更喜欢传入您需要的任何模型在包含该组件的模板中。

但是,如果您出于某种原因确实需要它,那么为什么不将变量store传递给组件?

{{my-component store=store}}

然后,您只能在您真正需要的组件中传递控制器中的store

在所有组件中注入store很可能会导致设计错误(尽管最初看起来很诱人)。

答案 1 :(得分:3)

以下是Ember 2的更新答案:

Ember Data的商店现在为Service,我们可以通过inject轻松Initializer到所有组件中,例如app/initializers/inject-store-into-components

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

export default {
  name: 'inject-store-into-components',
  initialize,
}

然后,在您的组件中,您可以使用this.get('store')访问商店。无需直接将商店作为参数传递给组件,这需要模板中的大量样板。

答案 2 :(得分:1)

虽然接受的答案对于简单的应用程序是明智的,但如果该组件与该URL没有关系,例如侧栏内容或仪表板上的可配置小部件,则将商店注入组件是完全可以接受的。

在这种情况下,您可以使用初始化程序将商店注入您的组件。

然而,初始化器可能是模仿测试的痛苦。我非常希望测试友好的优秀Ember.inject API将扩展到服务之外并容纳商店。 (或者商店将简单地成为服务)。

答案 3 :(得分:0)

根据this doc将商店注入组件的首选方法是将商店变量设置为记录,例如

{{#each item in arrangedContent}}
<li> {{my-component store=item}} </li>
{{/each}}

然后在应用程序代码中,您可以执行

var store = this.get('store');
store.set('todo', bufferedTitle);