我正在构建一个具有如下布局的应用程序。
preview http://sunshineunderground.kr/problem-01.png
我想创建一个新帖子,所以我按下了“新帖子按钮”,它把我带到了“帖子/新帖”。
My PostsNewRoute如下(我按照here描述的方法)
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;
}
});
它会立即创建新记录,更新帖子列表,并显示新帖子的表单。
preview http://sunshineunderground.kr/problem-02.png
现在我有两个问题。
一个是帖子列表的顺序。
我预计新帖子会在列表的顶部,但它位于列表的底部。
我使用rails作为我的后端,并将Post模型顺序设置为
default_scope order('created_at DESC')
旧帖子位于现有帖子的下方。但新创建的不是。 (它还没有被提交到后端)
另一种是当我点击列表中创建的帖子时
我可以在帖子列表中点击我新创建的帖子。它带我到了一个带有URL
的帖子页面 /posts/null
这是我必须阻止的非常奇怪的行为。
我认为会有两种解决方案。
当我点击“新发布按钮”时,立即创建一条记录并提交服务器,当服务器成功保存我的新记录后,刷新帖子列表并进入新创建的帖子的编辑模式。
< / LI>或者最初将Route的模型设置为null并在我单击PostsNewView中的“提交”按钮时创建记录。
或仅显示属性为
的帖子 'isNew' = false, 'isDirty' = false,
..
但遗憾的是,我不知道从哪里开始......
对于解决方案1,我完全迷路了。
对于解决方案2,我不知道如何将输入表单中的数据绑定到尚未存在的模型。
对于解决方案3,我完全迷路了。
请帮帮我!这将是余烬的预定方式?
(我听说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}}
更新
我通过过滤'arrangeContent'而不是'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')
});
答案 0 :(得分: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”在帖子上触发就会执行。此承诺仅在从服务器返回后才转换到帖子的路由,因此它将具有正确的ID。
答案 1 :(得分:3)
确实,写得非常好。谢谢。
您的filteredContent
不得使用isNew
州i.o. 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>
这只会在保存后显示帖子对象。 H3-tag中的url还包含新创建的对象i.o的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);
答案 2 :(得分:0)
我实际上写了一个函数来反转内容数组:
http://andymatthews.net/read/2012/03/20/Reversing-the-output-of-an-Ember.js-content-array
这是一篇非常古老的文章,差不多一年了,所以它可能无法正常工作,但框架就在那里......
你可以在我写的这个迷你应用程序中看到它的实际效果:
http://andymatthews.net/code/emberTweets/
在顶部的输入字段中搜索用户,并按照从最新到最旧(而不是从最旧到最新)的顺序显示左侧。