【问题标题】:When to call createRecord and how to handle store transactions何时调用 createRecord 以及如何处理存储事务
【发布时间】:2013-04-28 14:32:03
【问题描述】:

我刚开始使用 Ember.js,我想实现一个非常简单的流程。

在概览屏幕上,我有一个允许用户添加记录的新按钮。保存后,用户将返回到概览屏幕,在该屏幕上他可以在概览中看到新创建的记录。

用户使用 linkTo 导航到“新记录”页面

{{#linkTo locations.new}} Insert location {{/linkTo}}

这会触发以下路线,准备新模型以便将其绑定到屏幕。

App.LocationsNewRoute = Ember.Route.extend({
  model: function() {
    return App.Location.createRecord();
  }
});

新位置屏幕的车把模板如下所示:

<script type="text/x-handlebars" data-template-name="locations/new">
   <h1>New location</h1>
   Latitude :  {{view Ember.TextField valueBinding="latitude"}}
   Longitude : {{view Ember.TextField valueBinding="longitude"}}
   <p><button {{action addItem this}}>Add record</button></p>
</script>

addItem 是这样实现的:

App.LocationsNewController = Ember.ObjectController.extend({
  addItem: function(location) {
    this.get("store").commit();
    this.get("target").transitionTo("locations");

  }
});

我遇到的几个问题:

模型商店交易

  • 只要用户导航(使用 linkTo)到新的位置页面,就会创建一个空记录(使用 createRecord)。我相信这是将控件绑定到模型所必需的。
  • 我注意到,当用户填写纬度,但决定返回概览时(使用 linkTo),部分填充的模型会被放入概览中。
  • 刷新页面会移除部分填充的对象

我在使用 Ember.js 时注意到了很多......通过 linkTo 转换到新路由和在浏览器中刷新它之间的区别有时是巨大的。

问题:我需要使用什么模式来实现“添加新记录”流程。我只是想导航到一个新屏幕并有一个保存/取消按钮。我只希望在单击保存时添加记录。 createRecord 是否应该仅在单击保存时调用,但是如何绑定控件?

模型重复

当我的 REST 服务在执行 POST(添加记录)后返回以下(非 ember.js 标准)JSON 时:

{
  "latitude": "1.123",
  "longitude": "1.123",
  "accuracy": null,
  "_id": "517d2dcf377dcffc11000009"
}

我得到以下行为:

  • 当用户填写纬度/经度并点击保存按钮时,他返回概览,在概览中两次找到他新创建的记录。
  • 点击保存后,控制台显示错误:您的服务器返回了一个带有密钥纬度的哈希值,但您没有它的映射。
  • 刷新页面消除了重复。

我可以通过在 POST 后返回 ember.js 标准 JSON 来解决这个问题

{
  "location": {
    "latitude": "1.123",
    "longitude": "1.123",
    "accuracy": null,
    "_id": "517d31457b40fcbc2a000003"
  }
}

应用程序配置为使用 _id 作为主键,因为我使用的是 mongodb。

App.Adapter = DS.RESTAdapter.extend({
  serializer: DS.RESTSerializer.extend({
    primaryKey: function (type){
      return '_id';
   }
  })
});

我现在可以理解为什么 Ember.js 会抱怨纬度键(因为它需要一个位置根元素),但我不明白为什么它将模型两次添加到集合中(仅使用 1 个 POST)

所以 2 个问题:

  • 我的流程出了什么问题,我该如何解决?
  • 当 REST api 返回非 ember.js 标准 JSON 时,为什么我最终会出现重复。

【问题讨论】:

标签: ember.js ember-data


【解决方案1】:

模型商店交易

将您的创作包装到新事务中。这不会阻止记录在列表中可见(您始终可以过滤列表以拒绝新记录)。在您的路由器中,您可以在退出状态时回滚事务。比如:

App.LocationsNewRoute = Ember.Route.extend({
  activate: function() {
    this.transaction = DS.defaultStore.transaction(),
  },

  model: function() {
    return this.transaction.createRecord(App.Location);
  }
});

在您的save 处理程序中,您希望提交记录的事务(而不是存储的默认事务)。

更新:不要回滚deactivate

模型重复

“您的服务器返回了一个带有密钥纬度的散列,但您没有它的映射。” Ember 数据试图旁加载 JSON 中返回的每个属性/键。 Ember 数据期望返回的对象位于 JSON 中的根键下(如您所见)。

我不知道你为什么有重复。

更新 2:如何不显示新创建的记录

我在我的 cmets 中说错了,在事务中创建的记录属于 find 返回的数组。我忘了我已经更新了我的代码来做到这一点:

App.LocationsController = Ember.ArrayController.extend({
  persisted: function() {
    return this.get('arrangedContent').filter( function(contact) {
      if( !contact.get('isNew') ) {
        return true;
      }
    });
  }.property('arrangedContent.@each.isNew', 'arrangedContent')
})

然后在你的模板中:

{{#each persisted}}
  // whatever you need
{{/each}}

【讨论】:

  • Ember.JS 的“新记录”页面真的会强迫您实际创建新记录吗?过滤真的有必要吗?如果有,我该如何过滤?看起来很奇怪......如果用户在我的“新记录”按钮上点击 100 次,我不想在我的事务中有 100 个空对象。
  • 如果记录没有保存,可以回滚deactivate中的事务
  • 尝试了解决方案,虽然在离开 LocationsNewRoute 路线时调用了 deactivate,但当返回到我的 LocationsIndexRoute 时,App.location.find() 方法仍然返回我正在处理的项目(但不保存)在位置/新模板中。
  • 但是如果我不回滚“新记录”仍然在列表中。过滤掉该记录的正确方法是什么?事实上,我想我想在这里做一个回滚,因为用户显然决定“不保存”记录并开始在应用程序中做其他事情。
  • @Cyril - 如果用户开始在“新记录”页面中输入,它最终会出现在列表中并且 find() 会返回它。很可能是由于值绑定。你如何定义“从未得救”?
猜你喜欢
  • 1970-01-01
  • 2013-01-13
  • 2023-03-31
  • 2018-05-28
  • 2020-01-10
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
  • 2015-07-22
相关资源
最近更新 更多