Liftでdate_select系ヘルパーを作る

Liftに日付入力SELECTを生成するヘルパーが無かったので、作ってみました。Lift1.1-M8です。そんなにうまくできてるわけではありませんが、困ってる人いたら参考にしてみてください。

DateSelect

import _root_.net.liftweb.http._
import _root_.net.liftweb.util._
import _root_.net.liftweb.common._
import _root_.scala.xml._

import _root_.java.text.SimpleDateFormat
import _root_.java.util.{Date,Calendar,GregorianCalendar}
import _root_.java.lang.Integer.parseInt //メソッド毎importできる

object DateSelect {

  def apply(vars: AnyVar[String,_],name:String) = new DateSelect(vars,name)

  val dummyYMD = "1970/01/01"
  private val formatterYMD = new SimpleDateFormat("yyyy/MM/dd")
  def parseYMD(ymd:String):Date
     = synchronized{ formatterYMD.parse(ymd) }
  def formatYMD(date:Date):String
     = synchronized{ formatterYMD.format(date) }
  def YMD2Calendar(ymd:String) = {
    val cal = new GregorianCalendar
    cal.setTime(DateSelect.parseYMD(ymd))
    cal
  }
  def splitYMD(ymd:String):(String,String,String) = {
    val cal = YMD2Calendar(ymd)
    val y = cal.get(Calendar.YEAR).toString
    val m = (cal.get(Calendar.MONTH)+1).toString
    val d = cal.get(Calendar.DATE).toString
    (y,m,d)
  }

  def toOpts(from:Int,to:Int,by:Int):Seq[(String,String)] =
    (from to to by by).map( i => i.toString -> i.toString )
  def toOpts(from:Int,to:Int):Seq[(String,String)] = toOpts(from,to,1)

  def toDate(y:String,m:String,d:String)
  = new GregorianCalendar(parseInt(y),parseInt(m)-1,parseInt(d)).getTime
}

class DateSelect(vars:AnyVar[String,_],name:String) {

  def currentYMD = if( vars.is == DateSelect.dummyYMD ){
    DateSelect.formatYMD(new Date)
  } else vars.is

  def date_html(attrs: (String, String)*): NodeSeq = {

    //SELECTパラメータを受け取って組み立て、
    //RequestVarへ入れるコールバック
    //hidden要素にバインドする。
    val callback = (s:String) => {
      val passedDate = DateSelect.toDate(
        S.param(name+"_y").open_!,
        S.param(name+"_m").open_!,
        S.param(name+"_d").open_! )
      vars( DateSelect.formatYMD( passedDate ) )
    }

    val (y,m,d) = DateSelect.splitYMD(currentYMD)

    SHtml.hidden( callback, currentYMD ) ++
    SHtml.select( DateSelect.toOpts(2009, 2011), Full(y), null,
    attrs ++ Seq(("name",name+"_y")): _*) ++
    SHtml.select( DateSelect.toOpts(1, 12), Full(m), null,
    attrs ++ Seq(("name",name+"_m")): _*) ++
    SHtml.select( DateSelect.toOpts(1, 31), Full(d), null,
    attrs ++ Seq(("name",name+"_d")): _*)
  }
}

使い方

class ASnippet {

  object startTime extends RequestVar[String](DateSelect.dummyYMD)
  object endTime extends RequestVar[String](DateSelect.dummyYMD)

  def addForm(xhtml: NodeSeq):NodeSeq = {

    def doAdd(){
      println("---startTime:" + startTime)
      println("---endTime:" + endTime)
    }

    bind("e", xhtml,
      "startTime" -> DateSelect(startTime,"startTime").date_html(),
      "endTime" -> DateSelect(endTime,"endTime").date_html(),
      "submit" -> SHtml.submit("送信", doAdd) )
  }
}

特に難しいことはやってないですが、ポイントは、

・HIDDEN要素に、サーバサイドコールバックのトリガーを持たせる。
・SELECT要素は文字列の運搬だけを行う。name属性は上書き。
・RequestVarでもSessionVarでも使えるようにAnyVarを使う。

※値を入力できるSHtml.hiddenはLift1.0では使えないので、何か別の方法考える必要あります。


要点だけ絞ったコードを貼りました(コピペで使えるはずです)が、時間も設定できるようにするにはパターンを増やすだけ。完成品ができたら後でgistにでも貼っておきます。


DATE SELECTがないことに今頃気づいて「げげぇっ」って感じで、自分も困ってる人なので、他に良案・良実装があれば教えていただければ幸いです。


同じカテゴリのエントリ
1.Lift再入門 / 8.javascriptからsubmitできない / 7.Ajax Form / 6.Radio、Checkboxについて / 5.行列型の編集FORM / 4.サーバーサイドバリデーションとサーバサイド関数 / 3.ログインFORM - S.param使ったら負け / 2.Snippetメソッドとして許される型 / sbt0.12.xで依存jar抽出タスク / scala2.10+lift2.5+NetBeans7.2 / Scalaで入門関数プログラミング / reactive-webを試してみました / Lift2.2M1のテンプレート機能 / Scala Compiler Plugin / View Bound/Context Bound / ScalaZa01参加してきました / Akka Frameworkチュートリアルの次 / Akka Frameworkチュートリアルその2 / Akka Frameworkチュートリアル / LiftでJCaptcha / Url Rewrite Filter / sbt-android-plugin / Android SDK for Scala / 祝Lift2.0リリース / Liftの携帯対応まとめ / Scala2.8への移行 / Lift 2.0-scala280-SNAPSHOT/sbt0.7.1 / Scalaお絵かき環境 - Kojo / Lift+Quartzでバッチ / Scala&Liftを採用した理由 / Liftでdate_select系ヘルパーを作る / LiftでAjax / LiftのSubmitかしこい / lift-mapperのpaginateを使う / snippetをspecする / Lift Mapperを拡張する / LiftのDBをMySQLに / Liftプロジェクト環境を整える / Scala本読み比べてみました / NetBeans6.7&scala / じつはScalaはライトな言語 / Scalaバザ~ル / lift1.0所感 / specsを読む / implicit def / ScalaならNetBeansがサイコー / scala勉強会@東北がスタート / それでも俺はLiftをやるってのか / Scala&Liftセットアップ / ブログリニューアル /
コメント

コメントしてください

closed.