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}; };