ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

【PlayFramework】Form.Classに振り回されてワロタ

スポンサードリンク

photo by Hamad AL-Mohannna

前回の続き。

aipacommander.hatenablog.jp

何がしたいのか。編集画面でcheckboxに登録済みだったらcheckedをいれてほしいだけなんだ!!

ソース

呼び元

@manyToManyInputHidden(field = formValue("testValue"),
    options(models.TestClass.getList),
    'name -> "testValue.testValueName")

呼び出し先

@(field: play.api.data.Field, options: Seq[(String,String)], args: (Symbol,Any)*)(implicit handler: FieldConstructor)
@import play.Logger

@input(field, args.map{ x => if(x._1 == '_label) '_name -> x._2 else x }:_*) { (id, name, value, htmlArgs) =>
    @defining(field.indexes.map( i => field("[%s]".format(i)).value ).flatten.toSet) { values =>
        @Logger.debug(field("[0]").value.toString)
        @options.map { v =>
            <input type="hidden" id="@(id)_@v._1" name="@{name + "[]"}" value="@v._1" @if(values.contains(v._1)){ "checked" } @toHtmlArgs(htmlArgs)/>
      }
    }
}
  • models.TestClass.getList
public static final Finder<Long, TestClass> FINDER = new Finder<Long, TestClass>(Long.class, TestClass.class);

/**
 * getデータ
 */
public static Map<String, String> getList() {
    List<TestClass> testValues = FINDER.all();
    Map<String, String> resultList = new TreeMap<String, String>();
    for (TestClass testValue : testValues) {
        resultList.put(testValue.id.toString(), testValue.testValueName);
    }
    return resultList;
}

debugしてみる

@import play.Logger

@Logger.debug(field.toString)
@* [debug] application - Field(null,testValue,ArrayBuffer(),None,ArrayBuffer(),Some(BeanList deferred )) *@


@Logger.debug(field("[0]").toString)
@* [debug] application - Field(null,testValue[0],ArrayBuffer(),None,ArrayBuffer(),Some(models.TestClass@3)) *@


@Logger.debug(field("[0]").value.toString)
[debug] application - Some(models.TestClass@3)


@Logger.debug(field("[0]").value..filedName.toString)
@* compile error: value testValueName is not a member of Option[String] *@

私はわけがわからないよ。。。。。

と、思いましたが、わけがわからないのは俺でした。

Form.Field (playframework)

value() - Returns the field value, if defined.

ほげえええええ!!!ずっとObjectと信じていたんだ!!!(´;ω;`)ブワッ

え、じゃあどうすればマッチングかけることができるの?

んーと・・・???

valueの値はSome(models.TestClass@3)みたいなStringになるので(何故String・・・?) その後のソースも変更しないといけなくね。

えと、だって、ここで@options.map { v =>vには、(0 => "value")みたいな値が入るので、ObjectをStringにした値でない。

なにこれ。。。?値の渡し方が間違っているのか。。。?

よくわかっていないけど、とりあえずテンプレートにあわせたコードを書いてみる。

コードを改変してみる

とりま、modelsクラスから取得している値をindex => object.toStringに変更する。

  • models.TestClass.getObjectToStringList
public static final Finder<Long, TestClass> FINDER = new Finder<Long, TestClass>(Long.class, TestClass.class);

/**
 * getデータ
 */
public static Map<String, String> getObjectToStringList() {
    List<TestClass> testValues = FINDER.all();
    Map<String, String> resultList = new TreeMap<String, String>();
    for (TestClass testValue : testValues) {
        resultList.put(testValue.id.toString(), testValue.toString());
    }
    return resultList;
}

そして、呼び出し先のScalaを変更

呼び出し先

@(field: play.api.data.Field, options: Seq[(String,String)], args: (Symbol,Any)*)(implicit handler: FieldConstructor)
@import play.Logger

@input(field, args.map{ x => if(x._1 == '_label) '_name -> x._2 else x }:_*) { (id, name, value, htmlArgs) =>
    @defining(field.indexes.map( i => field("[%s]".format(i)).value ).flatten.toSet) { values =>
        @Logger.debug(field("[0]").value.toString)
        @options.map { v =>
            @Logger.debug(v._2.toString)
            <input type="hidden" id="@(id)_@v._1" name="@{name + "[]"}" value="@v_1" @if(values.contains(v._2)){ "checked" } @toHtmlArgs(htmlArgs)/>
      }
    }
}

そしたらできました。

なにか拭い切れないまとめ

今の気持ちはこんな感じ。

f:id:aipacommander:20150809193011j:plain

どゆこと?バグなの?

恐らくそんなことは無いはずなので、俺が何かしら引数で渡すoptionsの渡し方が間違っているとは思いますが、、、

でも、編集ページで渡す値はformValue("")であって、その変換の値はindex => objectになるはずなんだが。。。

ようわからないので、とりあえずできたということで。ノシ