18

我正在构建一个具有如下布局的应用程序。

预览

我想创建一个新帖子,所以我按下了“新帖子按钮”,它把我带到了“帖子/新”路线。

我的 PostsNewRoute 如下所示(我按照这里描述的方法)

 App.PostsNewRoute = Ember.Route.extend({
     model: function() {

           // create a separate transaction, 

           var transaction = this.get('store').transaction();

           // create a record using that transaction

           var post = transaction.createRecord(App.Post, {
                title: 'default placeholder title',
                body: 'default placeholder body'
           });

          return post;
     } 
 });

它会立即创建一条新记录,更新帖子列表,并显示新帖子的表单。

预览
(来源: sununderground.kr )

现在我有两个问题。

一是帖子列表的顺序。

我预计新帖子会在列表的顶部,但它在列表的底部。

我使用 rails 作为后端,并将 Post 模型顺序设置为

 default_scope order('created_at DESC')

所以旧帖子位于现有帖子的下方。但新创建的不是。(尚未提交到后端)

另一个是当我单击列表中的已创建帖子时

我可以在帖子列表中单击我新创建的帖子。它把我带到了一个带有 URL 的帖子页面

 /posts/null

这是我必须防止的非常奇怪的行为。

我认为会有两种解决方案。

  1. 当我单击“新帖子按钮”创建记录并立即提交到服务器时,当服务器成功保存我的新记录时,刷新帖子列表并进入新创建帖子的编辑模式。

  2. 或最初将 Route 的模型设置为 null 并在我单击 PostsNewView 中的“提交”按钮时创建一条记录。

  3. 或 show 仅显示属性为

        'isNew' = false, 'isDirty' = false, 
    

在列表中..

但可悲的是,我不知道从哪里开始……

对于解决方案 1,我完全迷路了。

对于解决方案 2,我不知道如何将输入表单中的数据与尚不存在的模型绑定。

对于解决方案 3,我完全迷路了。

请帮我!这将是 ember 的预期方式?

(我听说 Ember 打算为每个开发人员使用相同的解决方案)

更新

现在我正在使用解决方案 3,但仍然有订购问题。这是我的帖子模板代码。

    <div class="tools">
        {{#linkTo posts.new }}new post button{{/linkTo}}
    </div>
    <ul class="post-list">
        {{#each post in filteredContent}}
        <li>
            {{#linkTo post post }}
                <h3>{{ post.title }}</h3>
                <p class="date">2013/01/13</p>
                <div class="arrow"></div>
            {{/linkTo}}
        </li>
        {{/each}}
    </ul>
    {{outlet}}

更新

我通过过滤“arrangedContent”而不是“content”解决了这个问题

 App.PostsController = Ember.ArrayController.extend({
   sortProperties: ['id'],
   sortAscending: false,
   filteredContent: (function() {

     var content = this.get('arrangedContent');

     return content.filter(function(item, index) {
       return !(item.get('isDirty'));
     });
   }).property('content.@each')

 });
4

3 回答 3

8

我们在应用程序的几个地方使用了解决方案 3 的变体。恕我直言,它是 3 中最干净的,因为您不必担心服务器端的设置/拆卸这是我们实现它的方式:

App.PostsController = Ember.ArrayController.extend({
  sortProperties: ['id'],
  sortAscending: true,
  filteredContent: (function() {
    return this.get('content').filter(function(item, index) {
      return !(item.get('isDirty'));
    });
  }).property('content.@each')
});

然后在您的帖子模板中,您循环通过 controller.filteredContent 而不是 controller.content。

对于解决方案 1,有多种可能性。您可以定义以下事件:

  createPost: function() {
    var post,
      _this = this;
    post = App.Post.createRecord({});
    post.one('didCreate', function() {
      return Ember.run.next(_this, function() {
        return this.transitionTo("posts.edit", post);
      });
    });
    return post.get("store").commit();
  }

它创建帖子,然后设置一个承诺,一旦“didCreate”在帖子上触发,该承诺将被执行。这个promise只有在它从服务器返回后才会转换到post的路由,所以它会有正确的ID。

于 2013-02-05T11:05:48.090 回答
3

确实,写的很好。谢谢。

filteredContent不必使用isNew状态 io isDirty,否则正在编辑的帖子将不可见。在任何一种情况下,该filteredContent属性都不适用于我的情况。我还注意到,由于我使用图像作为每个元素的一部分,因此所有图像都会在filteredContent更改时刷新。这意味着我看到了对每张图片的请求。

我使用稍微不同的方法。我遍历内容并决定是否在模板中显示帖子:

# posts.handlebars
<ul class='posts'>
  {{#each controller}}
    {{#unless isNew}}
      <li>
        <h3>{{#linkTo post this}}{{title}}{{/linkTo}}</h3>
        <img {{bindAttr src="imageUrl"}}/>
        <a {{action deletePost}} class="delete-post tiny button">Delete</a>
      </li>
    {{/unless}}
  {{/each}}
</ul>

这只会在保存后显示Post对象。H3-tag 中的 url 还包含新创建的对象 io posts/null的 id 。

我在您的问题中注意到的另一件事:您可以在模型本身上使用 defaultValues 属性,而不是将默认值传递给 createRecord:

所以,而不是:

# App.PostsNewRoute
var post = transaction.createRecord(App.Post, {
            title: 'default placeholder title',
            body: 'default placeholder body'
       });

你可以这样做:

# App.Post
App.Post = DS.Model.extend({
  title: DS.attr('string', {
    defaultValue: "default placeholder title"
  }),
  body: DS.attr('string', {
    defaultValue: "default placeholder body"
  })
});

# App.PostsNewRoute
var post = transaction.createRecord(App.Post);
于 2013-02-16T16:44:49.240 回答
0

我实际上写了一个函数来反转内容数组:

http://andymatthews.net/read/2012/03/20/Reversing-the-output-of-an-Ember.js-content-array

那是一篇相当老的文章,差不多一年了,所以它可能无法按原样工作,但框架就在那里......

你可以在我写的这个迷你应用程序中看到它的实际效果:

http://andymatthews.net/code/emberTweets/

在顶部的输入字段中搜索用户,并观察左侧按从最新到最旧(而不是最旧到最新)的顺序显示。

于 2013-02-28T20:24:22.540 回答