如何将 JavaScript 中的数组变量传递给接受 List[String] 作为参数的控制器?

2023-11-30

设置:

使用“玩”!框架 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

我还使用了中提到的代码这个问题允许绑定List[String]作为参数。

问题

参数在请求中传递,如下所示:

PUT /admin/users?user=506b5d70e4b00eb6adcb26a7%2C506b6271e4b00eb6adcb26a8

编码后的%2C字符是逗号。控制器将其解释为单个字符串,因为上面代码中的调试行如下所示:

[debug] application - Admin.approve: ::506b5d70e4b00eb6adcb26a7,506b6271e4b00eb6adcb26a8

(使用默认的List.toString具有误导性,这就是我使用的原因foldLeft trick).

So

如何将复选框选定用户的列表传递给控制器​​,以便将其解释为字符串列表,而不是单个字符串列表?


好的。问题出在旧的实现中QueryBinders缺少 JavaScript 部分。正确的版本是:

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

最后一切正常。

最后说明:

在剧中! Framework 2.1+ 它应该可以在不添加项目源代码的情况下工作。实际上代码是按原样借用的Play20/framework/src/play/src/main/scala/play/api/mvc/Binders.scala

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 JavaScript 中的数组变量传递给接受 List[String] 作为参数的控制器? 的相关文章

随机推荐