使用Play!框架v 2.0.4
控制器:
def javascriptRoutes = Action { implicit request =>
Ok(
Routes.javascriptRouter("jsRoutes")(
routes.javascript.Admin.approve
)
).as("text/javascript")
}
def approve(user: List[String]) = SecureAction('admin) { implicit ctx =>
Logger.debug("Admin.approve: " + user.foldLeft("")(_ + "::" + _))
user map { u =>
User.approve(u)
}
Ok(Json.toJson(user))
}
观点:
function get_selected() {
return $.makeArray($(".user-selector").map(function (ind, user){
if(user.checked) return user.name;
}));
}
$("#button-approve").click(function(){
jsRoutes.controllers.Admin.approve(get_selected()).ajax({
success: function(data, status) {
console.log("Users activated: " + data)
for(i = 0; i < data.length; i++) {
id = "#" + data[i];
$(id + " > td > i.approved").removeClass("icon-flag").addClass("icon-check");
}
$(":checked").attr("checked", false);
}
});
});
路线:
PUT /admin/users controllers.Admin.approve(user: List[String])
GET /admin/jsRoutes controllers.Admin.javascriptRoutes
我还使用了this question中提到的代码,允许将List[String]
绑定为参数。
参数在如下报告的请求中传递:
PUT /admin/users?user=506b5d70e4b00eb6adcb26a7%2C506b6271e4b00eb6adcb26a8
编码的%2C
字符是逗号。控制器将其解释为单个字符串,因为上面代码中的调试行如下所示:
[debug] application - Admin.approve: ::506b5d70e4b00eb6adcb26a7,506b6271e4b00eb6adcb26a8
(使用默认List.toString
误导了我使用foldLeft
技巧的原因。
如何将复选框选定用户列表传递给控制器,以便将其解释为字符串列表,而不是单个字符串列表?
答案 0 :(得分:0)
确定。问题出在遗留JavaScript部分的QueryBinders
的旧实现中。正确的版本是:
package models
import play.api.mvc.{JavascriptLitteral, QueryStringBindable}
//TODO: remove when updating to 2.1
object QueryBinders {
/**
* QueryString binder for List
*/
implicit def bindableList[T: QueryStringBindable] = new QueryStringBindable[List[T]] {
def bind(key: String, params: Map[String, Seq[String]]) = Some(Right(bindList[T](key, params)))
def unbind(key: String, values: List[T]) = unbindList(key, values)
/////////////// The missing part here...:
override def javascriptUnbind = javascriptUnbindList(implicitly[QueryStringBindable[T]].javascriptUnbind)
}
private def bindList[T: QueryStringBindable](key: String, params: Map[String, Seq[String]]): List[T] = {
for {
values <- params.get(key).toList
rawValue <- values
bound <- implicitly[QueryStringBindable[T]].bind(key, Map(key -> Seq(rawValue)))
value <- bound.right.toOption
} yield value
}
private def unbindList[T: QueryStringBindable](key: String, values: Iterable[T]): String = {
(for (value <- values) yield {
implicitly[QueryStringBindable[T]].unbind(key, value)
}).mkString("&")
}
/////////// ...and here
private def javascriptUnbindList(jsUnbindT: String) = "function(k,vs){var l=vs&&vs.length,r=[],i=0;for(;i<l;i++){r[i]=(" + jsUnbindT + ")(k,vs[i])}return r.join('&')}"
/**
* Convert a Scala List[T] to Javascript array
*/
implicit def litteralOption[T](implicit jsl: JavascriptLitteral[T]) = new JavascriptLitteral[List[T]] {
def to(value: List[T]) = "[" + value.map { v => jsl.to(v)+"," } +"]"
}
}
现在查询如下:
PUT /admin/users?user=506b5d70e4b00eb6adcb26a7&user=506b6271e4b00eb6adcb26a8
最后一切正常。
在游戏中!框架2.1+它应该工作,而无需在项目源中添加代码。实际上,代码是从Play20/framework/src/play/src/main/scala/play/api/mvc/Binders.scala