[翻譯]Play框架1.2.7版本教程(4) - 瀏覽和提交評論

瀏覽和提交評論

博客主頁如今已經完成,接下來要完成博客正文頁面。整個頁面將展現當前文章的全部評論,還包括一個用於提交新的評論的表單。javascript

建立'show' action

要顯示文章內容,咱們須要在Application控制器添加新的action。就叫它show()html

public static void show(Long id) {
    Post post = Post.findById(id);
    render(post);
}

如你所見,整個action簡明扼要。咱們接受一個id參數做爲Long類型Java對象。而這個參數能夠來自於URL路徑或HTTP請求正文。java

若是接收到的id參數不是有效的數字,id的值會是null,而Play會在errors容器中新增一個驗證錯誤。jquery

這個action會顯示/yabe/app/views/Application/show.html模板:segmentfault

#{extends 'main.html' /}
#{set title:post.title /}

#{display post:post, as:'full' /}

由於以前寫好了display標籤,寫這個頁面就變得簡單。api

給正文頁面添加連接

在display標籤中,咱們讓全部的連接保持爲空(使用#)。是時候讓這些連接指向Application.show action。在Play模板中,你能夠簡單地用@{...}記號來建立連接。這個語法使用路由來「轉換」URL成對應的action。瀏覽器

修改/yabe/app/views/tags/display.html標籤:app

…
<h2 class="post-title">
    <a href="@{Application.show(_post.id)}">${_post.title}</a>
</h2>
…

如今刷新主頁,點擊一個標題來展現正文。函數

呃……好像缺了個返回主頁面的連接。修改/yabe/app/views/main.html模板來完成標題連接:post

…
<div id="title">
    <span class="about">About this blog</span>
    <h1><a href="@{Application.index()}">${blogTitle}</a></h1>
    <h2>${blogBaseline}</h2>
</div>
…

如今終於能夠在主頁和正文之間切換了。

指定一個更語義化的URL

如你所見,正文頁面的URL是:

/application/show?id=1

這是由於Play的默認路由規則就是這樣:

*       /{controller}/{action}                  {controller}.{action}

經過指定Application.show action的路徑,咱們可使用更語義化的URL。修改/yabe/conf/routes並在第一個路由下面添加新的路由:

GET     /posts/{id}                             Application.show

這裏id參數將從URL路徑提取。你能夠從Route File Syntax中閱讀更多關於URI模式的內容。

刷新瀏覽器,檢查此次是否使用了正確的URL。

添加分頁

要容許用戶在文章間方便地流連忘返,咱們須要添加分頁機制。咱們將拓展Post類來按需獲取上一篇和下一篇文章:

public Post previous() {
    return Post.find("postedAt < ? order by postedAt desc", postedAt).first();
}

public Post next() {
    return Post.find("postedAt > ? order by postedAt asc", postedAt).first();
}

這個方法在每次請求時都會被屢次調用,因此能夠優化它們,不過如今先擱置。同時,在show.html模板頂部(在#{display/}標籤前)添加分頁連接:

<ul id="pagination">
    #{if post.previous()}
        <li id="previous">
            <a href="@{Application.show(post.previous().id)}">
                ${post.previous().title}
            </a>
        </li>
    #{/if}
    #{if post.next()}
        <li id="next">
            <a href="@{Application.show(post.next().id)}">
                ${post.next().title}
            </a>
        </li>
    #{/if}
</ul>

如今是否是更棒了?

添加評論表單

是時候開始完成評論表單。先從在Application控制器中增長postComment action方法開始。

public static void postComment(Long postId, String author, String content) {
    Post post = Post.findById(postId);
    post.addComment(author, content);
    show(postId);
}

如你所見,咱們只是重用了以前添加給Post類的addComment()

show.html模板添加HTML表單(在#{display /}後面):

<h3>Post a comment</h3>

#{form @Application.postComment(post.id)}
    <p>
        <label for="author">Your name: </label>
        <input type="text" name="author" id="author" />
    </p>
    <p>
        <label for="content">Your message: </label>
        <textarea name="content" id="content"></textarea>
    </p>
    <p>
        <input type="submit" value="Submit your comment" />
    </p>
#{/form}

試下提交新的評論。它應該能工做。

comment

添加驗證

目前咱們沒有在建立評論以前驗證表單內容。咱們須要驗證表單中包括Comment類構造函數中的每一個參數。有了Play的驗證機制,添加驗證只是小菜一碟。修改postComment action來加入@Required驗證註解,並檢查有沒有錯誤產生:

public static void postComment(Long postId, @Required String author, @Required String content) {
    Post post = Post.findById(postId);
    if (validation.hasErrors()) {
        render("Application/show.html", post);
    }
    post.addComment(author, content);
    show(postId);
}

也不要忘了引入play.data/validation.*

如你所見,若是發生驗證錯誤,咱們從新輸出正文頁面。咱們須要修改表單代碼來顯示錯誤信息:

<h3>Post a comment</h3>

#{form @Application.postComment(post.id)}

    #{ifErrors}
        <p class="error">
            All fields are required!
        </p>
    #{/ifErrors}

    <p>
        <label for="author">Your name: </label>
        <input type="text" name="author" id="author" value="${params.author}" />
    </p>
    <p>
        <label for="content">Your message: </label>
        <textarea name="content" id="content">${params.content}</textarea>
    </p>
    <p>
        <input type="submit" value="Submit your comment" />
    </p>
#{/form}

注意到咱們重用已經提交的參數來填充HTML input元素的值。

爲了讓博客的用戶體驗更優,咱們將添加一點Javascript來自動聚焦到發生錯誤的地方。首先,須要JQueryJQuery Tools Expose,你得把它們引入進來。下載這兩個庫到yabe/public/javascripts/文件夾,並修改main.html模板來引入它們:

…
    <script src="@{'/public/javascripts/jquery-1.4.2.min.js'}"></script>
    <script src="@{'/public/javascripts/jquery.tools-1.2.5.toolbox.expose.min.js'}"></script>
</head>

注意當前版本的Play內置的JQuery要比教程用到的新。

如今你能夠在show.html模板底部添加這段代碼:

<script type="text/javascript" charset="utf-8">
    $(function() {         
        // Expose the form 
        $('form').click(function() { 
            $('form').expose({api: true}).load(); 
        }); 

        // If there is an error, focus to form
        if($('form .error').size()) {
            $('form').expose({api: true, loadSpeed: 0}).load(); 
            $('form input[type=text]').get(0).focus();
        }
    });
</script>

pretty page

如今評論框看起來真的美極了。咱們還有加多兩樣東西。

首先,咱們將在評論成功提交以後顯示一個成功信息。爲此,咱們須要使用flash做用域來容許咱們從一個action調用傳遞信息到下一個action。

修改postComment來添加成功信息:

public static void postComment(Long postId, @Required String author, @Required String content) {
    Post post = Post.findById(postId);
    if(validation.hasErrors()) {
        render("Application/show.html", post);
    }
    post.addComment(author, content);
    flash.success("Thanks for posting %s", author);
    show(postId);
}

並在show.html頂部添加可能顯示成功信息的位置:

…
#{if flash.success}
    <p class="success">${flash.success}</p>
#{/if}

#{display post:post, as:'full' /}
…

finish post page

最後咱們將修改postComment action所用的URL。由於咱們沒有給它指定路由,如今它用的是默認的路由。因此在應用的路由文件中添加下面一行:

POST    /posts/{postId}/comments                Application.postComment

終於完成了。記得把改動提交到bazaar。

相關文章
相關標籤/搜索