2年近く前、Wicket6 → 7 になった時、DropDownChoice の為の IChoiceRenderer が、
public T getObject(String id, IModel> choices)
が増えて、choices のgetModelObject() で取ってくるものをこのメソッドで返さなくてはならなくなり、
当時、以下のように、optionタグの value属性値を返せるようにするインターフェースを用意して
更に、IChoiceRenderer継承と、DropDownChoice がそれを使うように継承したものを作った。。
IChoiceRenderer ラムダ化 - Oboe吹きプログラマの黙示録
でも、やはりDropDownChoice の継承と、選択要素にoptionタグの value属性値を返せるようにするインターフェース
を付けるなんて方法は、選択要素の構造に手を加えるので良くない。
かと言って、IChoiceRenderer の無名インナークラスのコーディングは、長くなって嫌だ。
option タグの value を返すもの。bodyを返すもの。選択されたものを判断して返すもの。
これらの処理関数を埋め込めるラムダ式になっていれば良い。
import java.util.List; import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.model.IModel; import org.danekja.java.util.function.serializable.SerializableBiPredicate; import org.danekja.java.util.function.serializable.SerializableFunction; /** * IChoiceRenderer を提供 */ public class ChoiceRender{ private ChoiceRender(){} public static <T> IChoiceRenderer<T> of(SerializableFunction<T, String> idfunction , SerializableFunction<T, String> displayfunction , SerializableBiPredicate<T, String> bipredicate ){ return new IChoiceRenderer<T>(){ @Override public Object getDisplayValue(T t){ return displayfunction.apply(t); } @Override public String getIdValue(T t, int index){ return idfunction.apply(t); } @Override public T getObject(String id, IModel<? extends List<? extends T>> choices){ return choices.getObject().stream().filter(e->bipredicate.test(e, id)).findFirst().orElse(null); } }; } }
例)
以下のような対象クラスがあったとする。
public class Foo implements Serializable{ public int val; public String name; public Foo(int val, String name){ this.val = val; this.name = name; } }
final DropDownChoice<Foo> selectFoo = new DropDownChoice<Foo>("select1", new Model<>(), Arrays.asList(new Foo(1,"A"), new Foo(2,"B"), new Foo(3,"C") ) , ChoiceRender.of(t->Integer.toString(t.val), t->t.name, (t,u)->Integer.toString(t.val).equals(u)) ) ; queue(selectFoo);
そして、optionタグの value も body も同じものとして生成することも簡単に書ける。
例えば、"a","b","c"
final DropDownChoice<String> selectChar = new DropDownChoice<String>("select2", new Model<>(), Arrays.asList("a","b","c") , ChoiceRender.of(t->t, t->t, (t,u)->t.equals(u)) ) ; queue(selectChar);
フォーム送信されて受け取るところ。。
Optional.ofNullable(selectChar.getModelObject()).ifPresent(s->{ // });