以前のエントリ、AjaxRequestTarget#addComponent()で以下のような事を書いた。
llegalArgumentExceptionが投げられるようになっている。 結局、ListViewをdiv wicket:id="ListViewContainer"みたいな要素の内側に配置して、 ajaxRequestTarget#addComponent()にこのContainerを渡す、みたいな方法をとった。で、このContainer の実装として「org.apache.wicket.markup.html.border.BoxBorder」を使用した。 これでちゃんと動作しているから、困ってるという訳でも無いかもしれんけど、気分的には、こういう時に使うPanelとかBoxみたいなContainerとしてしか機能がないContainerを使いたい、あんまキレイじゃない、という気分。
が、WicketのWikiにこの件について「Working With AjaxRequestTarget」というページがあり、そのものズバリだった!
WebMarkupContainerというclassがそういった用途に使えるとの事。ちなみに、このclassはしょっちゅう出てくるので知ってはいたが、自分でインスタンスを作れるclassだとはちっとも思っていなかったw 基本的な事だろぅに、ちゃんと読めよ、俺。
- Do not add the view to a target. Use a parent component instead.
- If the view is within a Panel do not add the panel to the target. Use a WebMarkupContainer (or similar component) instead.
- Html
<html> <head> <title>Wicket Quickstart Archetype Homepage</title> </head> <body> <div><form wicket:id="myform"> <div><input type="text" wicket:id="text"/></div> <!-- Containerが必要。 --> <div wicket:id="listViewContainer"><ul> <li wicket:id="listView"><a href="#" wicket:id="label"></a></li> </ul></div></form></div> </body> </html>
- Page
import java.util.ArrayList; import java.util.List; import org.apache.wicket.PageParameters; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.OnChangeAjaxBehavior; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.behavior.IBehavior; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.MarkupStream; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.Model; public class HomePage extends WebPage { @SuppressWarnings("serial") public HomePage(final PageParameters parameters) { // myform final Form form = new Form("myform"); // myform/text final TextField text = new TextField("text", new Model("")); text.setOutputMarkupId(true); form.add(text); // myform/listViewContainer: WebMarkupContainerでListViewを包む。 WebMarkupContainer listViewContainer = new WebMarkupContainer("listViewContainer"); listViewContainer.setOutputMarkupId(true); form.add(listViewContainer); // myform/listViewContainer/listView listViewContainer.add(new ListView("listView", getLabelStrings()) { @Override protected void populateItem(ListItem item) { String labelString = item.getModelObjectAsString(); item.add(new AjaxLink("label", new Model(labelString)) { @Override public void onClick(AjaxRequestTarget target) { text.setModel(new Model(this.getModelObjectAsString())); target.addComponent(form.get("text")); } @Override protected void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) { super.replaceComponentTagBody(markupStream, openTag, this .getModelObjectAsString()); } }); } }); add(form); // text.add(newOnChangeAjaxBehavior(form)); } @SuppressWarnings("serial") private IBehavior newOnChangeAjaxBehavior(final Form form) { return new OnChangeAjaxBehavior() { @Override protected void onUpdate(AjaxRequestTarget target) { String textString = form.get("text").getModelObjectAsString(); ListView listView = (ListView) form.get("listViewContainer:listView"); List<String> filteredStrings = getLabelStrings(); if (textString != "") { filteredStrings.clear(); for (String label : getLabelStrings()) { if (label.indexOf(textString) >= 0) { filteredStrings.add(label); } } } listView.setList(filteredStrings); target.addComponent(form.get("listViewContainer")); } }; } private List<String> getLabelStrings() { List<String> labelStrings = new ArrayList<String>(); labelStrings.add("apple"); labelStrings.add("orange"); labelStrings.add("lemon"); labelStrings.add("banana"); labelStrings.add("grape"); return labelStrings; } }
- TestCase
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.util.tester.FormTester; import org.apache.wicket.util.tester.WicketTester; import org.junit.Before; import org.junit.Test; public class HomePageTest { private WicketTester tester; @Before public void setUp() { tester = new WicketTester(); tester.startPage(HomePage.class); tester.assertRenderedPage(HomePage.class); tester.assertNoErrorMessage(); } @Test public void testRenderMyPage() { tester.assertComponent("myform", Form.class); tester.assertComponent("myform:text", TextField.class); tester.assertComponent("myform:listViewContainer", WebMarkupContainer.class); tester.assertComponent("myform:listViewContainer:listView", ListView.class); tester.assertComponent("myform:listViewContainer:listView:0:label", AjaxLink.class); } @Test public void testAjaxLink() { FormTester formTester = tester.newFormTester("myform"); formTester.setValue("text", ""); // 0:"apple", 1:"orange", 2:"lemon", 3:"banana", 4:"grape" tester.clickLink("myform:listViewContainer:listView:0:label"); assertEquals("apple", formTester.getTextComponentValue("text")); tester.clickLink("myform:listViewContainer:listView:1:label"); assertEquals("orange", formTester.getTextComponentValue("text")); } @Test public void testAjaxEvent() { FormTester formTester = tester.newFormTester("myform"); final String textPath = "myform:text"; final String listViewPath = "myform:listViewContainer:listView"; ListView listView = (ListView) tester.getComponentFromLastRenderedPage(listViewPath); // 空文字の時はフィルタが働かない。全部表示される。 formTester.setValue("text", ""); tester.executeAjaxEvent(textPath, "onchange"); assertArrayEquals(new String[] { "apple", "orange", "lemon", "banana", "grape" }, listView.getList().toArray()); // "a"を含まない"lemon"が消える。 formTester.setValue("text", "a"); tester.executeAjaxEvent(textPath, "onchange"); assertArrayEquals(new String[] { "apple", "orange", "banana", "grape" }, listView.getList().toArray()); // "ap"を含む"apple","grape"が残る。 formTester.setValue("text", "ap"); tester.executeAjaxEvent(textPath, "onchange"); assertArrayEquals(new String[] { "apple", "grape" }, listView.getList().toArray()); } }
0 件のコメント:
コメントを投稿