[翻譯]Play框架1.2.7版本教程(9) - 自定義編輯區域

自定義編輯區域

在前一章,咱們給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

first

發佈文章界面

咱們將建立一個用於發佈文章的界面。通常對於一個表單,你能夠作兩件事:顯示它,處理它提交的結果。讓咱們建立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>
...

檢查成果:

result

如今咱們來完成處理提交結果的。它將建立一個新的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

完成了!如今咱們能夠用同一個方法來建立新的文章,或者修改舊的文章,並且管理面板也完成了!

相關文章
相關標籤/搜索