在前一章,咱们给yabe建立了一个关于面板,并准备了“个人文章”的部分。每一个做者能够在这个部分看到他们发布过的文章,以及进行编辑或者建立新的文章。html
咱们能够重用CRUD模块来实现这部分。可是这里咱们打算从头开始,由于咱们须要许多自定义的设置。java
咱们仅须要查询用户相关的文章并显示出来。这很简单。从改进Admin.index
action开始吧:segmentfault
public static void index() { String user = Security.connected(); List<Post> posts = Post.find("author.email", user).fetch(); render(posts); }
并完成yabe/app/views/Admin/index.html
:app
#{extends 'admin.html' /} <h3>Welcome ${user}, <span>you have written ${posts.size() ?: 'no'} ${posts.pluralize('post', 'posts')} so far</span></h3> #{list items:posts, as:'post'} <p class="post ${post_parity}"> <a href="#">${post.title}</a> </p> #{/list} <p id="newPost" > <a href="#"><span>+</span> write a new post</a> </p>
看看第一步的成果:post
咱们将建立一个用于发布文章的界面。通常对于一个表单,你能够作两件事:显示它,处理它提交的结果。让咱们建立Admin.form'和
Admin.save`来帮助显示和处理提交结果。测试
添加新的路由到yabe/conf/routes
:fetch
GET /admin/new Admin.form POST /admin/new Admin.save
接着给Admin.java
控制器添加form()
和save()
:this
public static void form() { render(); } public static void save() { // Not implemented yet }
而后是建立yabe/app/views/Admin/form.html
模板:spa
#{extends 'admin.html' /} <h3>Write, <span>a new post</span></h3> #{form @save()} #{ifErrors} <p class="error"> Please correct these errors. </p> #{/ifErrors} <p> #{field 'title'} <label>Post title:</label> <input type="text" name="${field.name}" value="${post?.title}" /> <span class="error">#{error 'post.title' /}</span> #{/field} </p> <p> #{field 'content'} <label>Write here:</label> <textarea name="${field.name}">${post?.content}</textarea> <span class="error">#{error 'post.content' /}</span> #{/field} </p> <p> #{field 'tags'} <label>Enter some tags:</label> <input type="text" size="50" name="${field.name}" value="${post?.tags?.join(' ')}" /> #{/field} </p> <p> <input type="submit" value="Publish this post to the blog" /> </p> #{/form}
最后修改yabe/app/views/Admin/index.html
,给表单添加Write a new post的连接:code
... <p id="newPost" > <a href="@{form()}"><span>+</span> write a new post</a> </p> ...
检查成果:
如今咱们来完成处理提交结果的。它将建立一个新的Post
对象,转换标签列表成真正的Tag
列表,并验证全部成员,进行保存。若是发生错误,它会刷新表单,显示错误信息。
public static void save(String title, String content, String tags) { // Create post User author = User.find("byEmail", Security.connected()).first(); Post post = new Post(author, title, content); // Set tags list for(String tag : tags.split("\\s+")) { if(tag.trim().length() > 0) { post.tags.add(Tag.findOrCreateByName(tag)); } } // Validate validation.valid(post); if(validation.hasErrors()) { render("@form", post); } // Save post.save(); index(); }
这里咱们使用
render("@form")
做为render("Admin/form.html")
的缩写。它表示使用form action的默认模板。
测试一下!
在发布文章的地方,咱们已经写了很多的HTML表单和Java action代码。但咱们还须要实现编辑现有文章的修改功能。只需改动一下,咱们能够重用原来的代码。
首先咱们须要Admin.form
能够查询到一个现有的Post
:
public static void form(Long id) { if(id != null) { Post post = Post.findById(id); render(post); } render(); }
如你所见,咱们把查询功能变成可选的,仅当id
参数不为空,才会去查询一个现有文章。因此你能够连接主页面的文章列表到编辑表单。修改yabe/app/views/Admin/index.html
:
#{extends 'admin.html' /} <h3>Welcome ${user}, <span>you have written ${posts.size() ?: 'no'} ${posts.pluralize('post', 'posts')} so far</span></h3> #{list items:posts, as:'post'} <p class="post ${post_parity}"> <a href="@{Admin.form(post.id)}">${post.title}</a> </p> #{/list} <p id="newPost" > <a href="@{form()}"><span>+</span> write a new post</a> </p>
很是简单,可是有一个问题。若是你查看这些连接生成的URL,会看到:
/admin/new?id=3
它能用,可是不是很好。咱们能够指定另外一个路由。若是指定了id
参数,就用新的路由。
GET /admin/myPosts/{id} Admin.form GET /admin/new Admin.form
如你所见,咱们在旧的路由之上定义新路由,因此它的优先级更高。这意味着,若是提交了id
参数,Play将选择这条路由。若是不是,它就选择原来那条。
刷新My posts页面,你应该能看到URL的变化。
如今咱们须要修改yabe/app/views/Admin/form.html
:
#{extends 'admin.html' /} #{ifnot post?.id} <h3>Write, <span>a new post</span></h3> #{/ifnot} #{else} <h3>Edit, <span>this post</span></h3> #{/else} #{form @save(post?.id)} #{ifErrors} <p class="error"> Please correct these errors. </p> #{/ifErrors} <p> #{field 'title'} <label>Post title:</label> <input type="text" name="${field.name}" value="${post?.title}" /> <span class="error">#{error 'post.title' /}</span> #{/field} </p> <p> #{field 'content'} <label>Write here:</label> <textarea name="${field.name}"> ${post?.content} </textarea> <span class="error">#{error 'post.title' /}</span> #{/field} </p> <p> #{field 'tags'} <label>Enter some tags:</label> <input type="text" size="50" name="${field.name}" value="${post?.tags?.join(' ')}" /> #{/field} </p> <p> <input type="submit" value="Publish this post to the blog" /> </p> #{/form}
如你所见,若是id
参数存在,咱们将用它做为提交表单的第一个参数。因此假如这个文章具备id的值(意味着它已经存在在系统中),Admin.save
就会被调用。
如今咱们改变save()
方法,让它同时能处理建立和修改文章的状况:
public static void save(Long id, String title, String content, String tags) { Post post; if(id == null) { // Create post User author = User.find("byEmail", Security.connected()).first(); post = new Post(author, title, content); } else { // Retrieve post post = Post.findById(id); // Edit post.title = title; post.content = content; post.tags.clear(); } // Set tags list for(String tag : tags.split("\\s+")) { if(tag.trim().length() > 0) { post.tags.add(Tag.findOrCreateByName(tag)); } } // Validate validation.valid(post); if(validation.hasErrors()) { render("@form", post); } // Save post.save(); index(); }
一如以前那样,咱们须要定义多一个更合适的路由,仍是用以前的方式:
POST /admin/myPosts/{id} Admin.save POST /admin/new Admin.save
完成了!如今咱们能够用同一个方法来建立新的文章,或者修改旧的文章,并且管理面板也完成了!