Xitrum学习笔记06 - 回发(Postback)

Xitrum提供了Ajax表单回发功能以支持 创建交互式的web页面

Xitrum的回发机制受了Nitrogen Web Framework的启发。

//AppAction.scala

import xitrum.Action
import xitrum.view.DocType

trait postbackTest extends Action {
  override def layout = DocType.html5(
    <html>
      <head>
        {antiCsrfMeta}
        <script type="text/javascript" src="/test/js/jquery.js"></script>
        <script type="text/javascript" src="/test/js/jquery.validate.js"></script>
        <script type="text/javascript" src="/test/js/additional-methods.js"></script>
        <script type="text/javascript" src="/test/js/sockjs.js"></script>
        <script type="text/javascript" src="/xitrum/xitrum-3.28.3.js"></script>
        <title>Test PostBack</title>
      </head>
      <body>
        {renderedView}
        {jsForView}
      </body>
    </html>
  )
}
//Form
//Articles.scala
import xitrum.annotation.{GET, POST, First}
import xitrum.validator._

@GET("test/articles/:id")
class ArticlesShow extends postbackTest{
  def execute(){
    val id = param[Int]("id")
    val article = Article.find(id)
    respondInlineView(
      <h1>{article.get.title}</h1>
      <div>{article.get.body}</div>
    )
  }
}

@First // Force this route to be matched before "show"
@GET("test/articles/new")
class ArticlesNew extends postbackTest{
  def execute(){
    respondInlineView(
//如果没有data-postback设置,点击Save后的URL地址就是http://localhost:8001/test/articles?title=a3&body=b3
//因为不符合已有的route而进入404.html
//设置data-postback后,url不会显示数据内容,且最终跳转到 http://localhost:8001/test/articles/3
      <form data-postback="submit" action={url[ArticlesCreate]}>
        <label>Title</label>
        <input type="text" name="title" class="required" /><br />
        <label>Body</label>
        <textarea name="body" class="required"></textarea><br />
        <input type="submit" value="Save" />
      </form>
    )
  }
}

@POST("test/articles")
class ArticlesCreate extends postbackTest{
  def execute(){
    val title = param("title")
    val body = param("body")
    val article = Article.save(title, body)
    flash("Article has been saved.")
    jsRedirectTo[ArticlesShow]("id" → article.id)
  }
}

case class Article(id: Int,
    title: String = "article title", body: String = "article body"){

}

object Article{
  private var storage = Map[Int, Article]()
  private var nextId = 1

  def findAll(): Iterable[Article] = storage.values
  def find(id: Int): Option[Article] = storage.get(id)

  def save(title: String, body: String): Article = synchronized {
    val article2 = Article(nextId, title, body)
    storage = storage + (nextId → article2)
    nextId += 1
    article2
  }

  save("a1", "b1")
  save("a2", "b2")
}

当form的submit事件被触发时,form会回发到ArticlesCreate。form的action的属性值会被加密。

 

回发可以被放到任何element上,不仅是form。放到链接上的示例:

<a href="#" data-postback="click" 
action
={url[LogoutAction]}
data-confirm="Do you wang to logout?"
>Logout</a> <!-- 点击链接会弹出确认窗口,Cancel就不会触发回发,否则就会触发回发到LogoutAction -->

有postback的元素的action所指向的Action的route一定要用post。

在这个例子中,我刻意把action的设置去掉后,点击确认按钮后,在Chrome“检查”>“Network”中,发现jquery.js中报出的错误。应该提供的是jquery的postback。

附加参数

1. 对于表单form元素,可以通过添加隐藏的input,如<input type="hidden" ...>,来在回发时传递附加参数

2. 对于其他元素可以使用data-params来传递附加参数

<!--For other elements, you do like this:-->
<a href="#"
   data-postback="click"
action={url[ArticlesDestroy]("id" -> item.id)} data-params="_method=delete" data-confirm={"Do you want to delete %s?".format(item.name)}>Delete</a>

3. 把附加参数放在一个单独的form中

<!--You may also put extra params in a separate form:-->
<form id="myform" data-postback="submit" action={url[SiteSearch]}>
Search:
<input type="text" name="keyword" />
<a class="pagination"
   href="#"
   data-postback="click"
   data-form="#myform"
   action={url[SiteSearch]("page" -> page)}>{page}</a>
</form>

#myform是一个jQuery选择器用来定位包含额外参数的form

自定义Ajax加载动画

默认的加载动画是 

src="/webjars/xitrum/3.28.3/ajax.gif?SIl4RonBuBCfl6Duz5Jl9A" 

要自定义加载动画的话,在View模板中的jsDefaults后面调用以下JS片段

// target: The element that triggered the postback
xitrum.ajaxLoading = function(target) {
  // Called when the animation should be displayed when the Ajax postback is being sent.
  var show = function() {
  ...

    // Display Ajax loading animation image
    target.after('<img id="' + ajaxLoadingImgId + '" src="""" + 自定义动画 + """" />');

  };
  // Called when the animation should be stopped after the Ajax postback completes.
  var hide = function() {
    ...
  };
  return {show: show, hide: hide};
};

 

posted @ 2017-05-15 16:29  子秦  阅读(297)  评论(0编辑  收藏  举报