09 Creating a custom editor area

簡介

在上一章節我們已經建立一個yabe管理介面並實現"My Posts(我的文章)"部分。本章節將為每一位作者建立清單並管理自己的文章以及進行編輯並新增新的文章。

我們可以很簡單的重構CRUD module為基礎在此頁面中,但是,這裡我們將要重新開始建立一些東西。我們需要大量個人化的頁面。


Start with the user posts list

我們只需要檢索和顯示用戶所編輯的文章。加強Admin.index() action:

public static void index() { List<Post> posts = Post.find("author.email", Security.connected()).fetch(); render(posts); }

並完成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="#">${post.title}</a> </p> #{/list} <p id="newPost" > <a href="#"><span>+</span> write a new post</a> </p>

第一個畫面完成。



The ‘write a new post’ page

我們將建立一個新增文章的表單。基本上表單上只有2個動作:處理表單提交並讓我們建立新的Admin.form 及 Admin.save actions,以便顯示及處理表單提交:

新增路徑於 yabe/conf/routes

GET /admin/new Admin.form POST /admin/new Admin.save

並增加form()save() actions Admin.java controller

public static void form() { render(); } public static void save() { // Not implemented yet }

現在你必須建立yabe/app/views/Admin/form.html模版:

#{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}" class="${field.errorClass}" /> #{/field} </p> <p> #{field 'content'} <label>Write here:</label> <textarea name="${field.name}" class="${field.errorClass}">${post?.content}</textarea> #{/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"按鈕在這個表單上:

... <p id="newPost" > <a href="@{form()}"><span>+</span> write a new post</a> </p> ...

你可以檢查一下結果。


現在,我們必須完成Admin.save action正確處理表單提交。這將建立一個新的Post object,將Tag list 轉換至真的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”)的捷徑。它只是告訴Play使用form action的預設模版。


Reusing this stuff for editing Posts

我們已經定義了HTML form和Java action並能夠建立一個新的Blog文章。但是,我們還須要有編輯已存在的文章。我們可以很方便地使用相同的程式碼做一些修改。首先,我們需要Admin.form檢視已存在的文章:

public static void form(Long id) { if(id != null) { Post post = Post.findById(id); render(post); } render(); }

在該action運用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參數提交後,將使用不同的URL模式:

GET /admin/myPosts/{id} Admin.form GET /admin/new Admin.form

正如你所看見我們所定義的路徑比起相對之前的來說它具有更高的優先權。這意味著,如果一個id參數提交,Play選擇這樣的URL模式。如果沒有,它仍然會使用較舊的路徑。現在若重新更新頁面,你應該可以看到更好的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}" class="${field.errorClass}" /> #{/field} </p> <p> #{field 'content'} <label>Write here:</label> <textarea name="${field.name}" class="${field.errorClass}">${post?.content}</textarea> #{/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}

正如你所看見的我們更新表單目的是新增post id作為第一個action參數,如果它存在的話。因此,當文章有一個id欄位(這意味著該文章已存在於系統當中),它將被發送至Admin.save action。

現在,我們可以改變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(); }

為了有更好的URL,我們可以用之前同樣的方式,通過新增加的首選路徑,如果有存在一個id參數:

POST /admin/myPosts/{id} Admin.save POST /admin/new Admin.save


OK了!!現在我們為"建立新的Blog文章"及"編輯已存在的文章"使用相同的action,而管理介面已經大功告成了!!




Comments