You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2014/07/09 12:03:06 UTC

git commit: WICKET-4344 Implement onValidateModelObjects() and beforeUpdateFormComponentModels() for nested forms

Repository: wicket
Updated Branches:
  refs/heads/wicket-6.x 3d146141d -> e193f4f4d


WICKET-4344 Implement onValidateModelObjects() and beforeUpdateFormComponentModels() for nested forms


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/e193f4f4
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/e193f4f4
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/e193f4f4

Branch: refs/heads/wicket-6.x
Commit: e193f4f4d5ef6ef9778a150a337236f208e2b060
Parents: 3d14614
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Wed Jul 9 13:02:12 2014 +0300
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Wed Jul 9 13:02:59 2014 +0300

----------------------------------------------------------------------
 .../apache/wicket/markup/html/form/Form.java    |  29 ++-
 .../html/form/OnValidateModelObjectsTest.java   |  51 ++++++
 .../AddressFormPanel.html                       |  27 +++
 .../AddressFormPanel.java                       | 151 ++++++++++++++++
 .../OnFormValidateModelObjectsPage.html         |  66 +++++++
 .../OnFormValidateModelObjectsPage.java         | 175 +++++++++++++++++++
 6 files changed, 496 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/e193f4f4/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
index 45dc345..1292896 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
@@ -927,7 +927,7 @@ public class Form<T> extends WebMarkupContainer implements IFormSubmitListener,
 			updateFormComponentModels();
 
 			// validate model objects after input values have been bound
-			onValidateModelObjects();
+			internalOnValidateModelObjects();
 			if (hasError())
 			{
 				callOnError(submittingComponent);
@@ -1844,6 +1844,30 @@ public class Form<T> extends WebMarkupContainer implements IFormSubmitListener,
 	}
 
 	/**
+	 * Calls {@linkplain #onValidateModelObjects()} on this form and all
+	 * nested forms that are visible and enabled
+	 */
+	private void internalOnValidateModelObjects()
+	{
+		onValidateModelObjects();
+		visitChildren(Form.class, new IVisitor<Form<?>, Void>()
+		{
+			@Override
+			public void component(Form<?> nestedForm, IVisit<Void> visit)
+			{
+				if (nestedForm.isEnabledInHierarchy() && nestedForm.isVisibleInHierarchy())
+				{
+					nestedForm.onValidateModelObjects();
+				}
+				else
+				{
+					visit.dontGoDeeper();
+				}
+			}
+		});
+	}
+
+	/**
 	 * Called after form components have updated their models. This is a late-stage validation that
 	 * allows outside frameworks to validate any beans that the form is updating.
 	 * 
@@ -1852,11 +1876,10 @@ public class Form<T> extends WebMarkupContainer implements IFormSubmitListener,
 	 * containing illegal values. However, with external frameworks there may not be an alternate
 	 * way to validate the model object. A good example of this is a JSR303 Bean Validator
 	 * validating the model object to check any class-level constraints, in order to check such
-	 * constaints the model object must contain the values set by the user.
+	 * constraints the model object must contain the values set by the user.
 	 */
 	protected void onValidateModelObjects()
 	{
-
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/wicket/blob/e193f4f4/wicket-core/src/test/java/org/apache/wicket/markup/html/form/OnValidateModelObjectsTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/OnValidateModelObjectsTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/OnValidateModelObjectsTest.java
new file mode 100644
index 0000000..b55ad57
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/OnValidateModelObjectsTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup.html.form;
+
+import static org.hamcrest.CoreMatchers.is;
+
+import org.apache.wicket.Page;
+import org.apache.wicket.WicketTestCase;
+import org.apache.wicket.markup.html.form.onFormValidateModelObjects.AddressFormPanel;
+import org.apache.wicket.markup.html.form.onFormValidateModelObjects.OnFormValidateModelObjectsPage;
+import org.apache.wicket.util.tester.FormTester;
+import org.junit.Test;
+
+/**
+ * Test case for https://issues.apache.org/jira/browse/WICKET-4344
+ */
+public class OnValidateModelObjectsTest extends WicketTestCase
+{
+	/**
+	 * Asserts that submitting the outer form will call {@link Form#onValidateModelObjects()}
+	 * for both the outer form and the inner form(s)
+	 */
+	@Test
+	public void onValidateModelObjects()
+	{
+		tester.startPage(OnFormValidateModelObjectsPage.class);
+		FormTester formTester = tester.newFormTester("parentForm");
+		formTester.submit("parentSubmitBtn");
+
+		Page page = tester.getLastRenderedPage();
+		OnFormValidateModelObjectsPage.ParentModel parentModel = (OnFormValidateModelObjectsPage.ParentModel) page.getDefaultModelObject();
+		assertThat(parentModel.isParentValidated(), is(true));
+
+		AddressFormPanel.ChildModel childPanel = (AddressFormPanel.ChildModel) page.get("parentForm:addressInfo").getDefaultModelObject();
+		assertThat(childPanel.isChildValidated(), is(true));
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/e193f4f4/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/AddressFormPanel.html
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/AddressFormPanel.html b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/AddressFormPanel.html
new file mode 100644
index 0000000..42d41f2
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/AddressFormPanel.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html xmlns:wicket="http://wicket.apache.org">
+  <body>
+    <wicket:panel>
+      <div>
+        <form wicket:id="childForm">
+            <label>Address 1:
+              <input type="text" wicket:id="address1"/>
+            </label>
+            <label>Address 2:
+              <input type="text" wicket:id="address2"/>
+            </label>
+            <label>City:
+              <input type="text" wicket:id="city"/>
+            </label>
+            <label>State:
+              <input type="text" wicket:id="state"/>
+            </label>
+            <label>Zip:
+              <input type="text" wicket:id="zip"/>
+            </label>
+        </form>
+        <input type="button" wicket:id="childSubmitButton" value="Child Submit Button"/>
+      </div>
+    </wicket:panel>
+ </body>
+</html>

http://git-wip-us.apache.org/repos/asf/wicket/blob/e193f4f4/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/AddressFormPanel.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/AddressFormPanel.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/AddressFormPanel.java
new file mode 100644
index 0000000..6fe5059
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/AddressFormPanel.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup.html.form.onFormValidateModelObjects;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+
+public class AddressFormPanel extends Panel
+{
+	public AddressFormPanel(String id, IModel<ChildModel> model)
+	{
+		super(id, model);
+
+		setupPanel();
+	}
+
+	private void setupPanel()
+	{
+		// create the form and add the fields and submit button
+		Form form = new Form("childForm", getDefaultModel())
+		{
+			@Override
+			protected void onValidateModelObjects()
+			{
+				super.onValidateModelObjects();
+				((ChildModel)getModelObject()).setChildValidated(true);
+			}
+		};
+
+		add(form);
+
+		// add all the form fields
+		form.add(new TextField("address1"));
+		form.add(new TextField("address2"));
+		form.add(new TextField("city"));
+		form.add(new TextField("state"));
+		form.add(new TextField("zip"));
+
+		// add the child submit button
+		add(new AjaxSubmitLink("childSubmitButton", form)
+		{
+			@Override
+			public void onSubmit(AjaxRequestTarget target, Form<?> form)
+			{
+				((ChildModel)getPanelInstance().getDefaultModelObject()).submittedCalled(target);
+			}
+		});
+	}
+
+	private AddressFormPanel getPanelInstance()
+	{
+		return this;
+	}
+
+	public abstract static class ChildModel
+	{
+		String address1 = "address1";
+		String address2 = "address2";
+		String city = "city";
+		String state = "state";
+		String zip = "zip";
+
+		boolean childValidated = false;
+
+		public String getAddress1()
+		{
+			return address1;
+		}
+
+		public void setAddress1(String address1)
+		{
+			this.address1 = address1;
+		}
+
+		public String getAddress2()
+		{
+			return address2;
+		}
+
+		public void setAddress2(String address2)
+		{
+			this.address2 = address2;
+		}
+
+		public String getCity()
+		{
+			return city;
+		}
+
+		public void setCity(String city)
+		{
+			this.city = city;
+		}
+
+		public String getState()
+		{
+			return state;
+		}
+
+		public void setState(String state)
+		{
+			this.state = state;
+		}
+
+		public String getZip()
+		{
+			return zip;
+		}
+
+		public void setZip(String zip)
+		{
+			this.zip = zip;
+		}
+
+		public boolean isChildValidated()
+		{
+			return childValidated;
+		}
+
+		public void setChildValidated(boolean childValidated)
+		{
+			this.childValidated = childValidated;
+		}
+
+		public void submittedCalled(AjaxRequestTarget target)
+		{
+			// do nothing here...(this is so parent can refresh the validations
+			// area)
+		}
+
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/e193f4f4/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/OnFormValidateModelObjectsPage.html
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/OnFormValidateModelObjectsPage.html b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/OnFormValidateModelObjectsPage.html
new file mode 100644
index 0000000..cf92333
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/OnFormValidateModelObjectsPage.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html xmlns:wicket="http://wicket.apache.org">
+  <head>
+    <meta charset="utf-8" />
+    <title>QUICKSTART APPLICATION for JIRA issue WICKET-4344</title>
+    <link href='https://issues.apache.org/jira/browse/WICKET-4344' rel='stylesheet' type='text/css' />
+    <link rel="stylesheet" href="style.css" type="text/css" media="screen" title="Stylesheet" />
+  </head>
+  <body>
+    <div id="hd">
+      <div id="logo">
+        <img src="logo.png" width="50px" height="50px" alt="Wicket Logo" />
+        <h1>Apache Wicket</h1>
+      </div>
+    </div>
+    <div id="bd">
+      <h2>Issue</h2>
+      <p>
+        Implementation of onValidateModelObjects() only works for the form that had its submit
+        button clicked.  This makes it difficult to have nested forms in the case where a child
+        form has implemented the onValidateModelObjects() to do extra validation after the model
+        has been updated from a submit (see Form.process() ).  Note within this project both the
+        parent form and the child form have overridden the onValidateModelObjects().
+
+        To test:
+          click on the child submit to see what got validated
+          hit reset to reset the validation values
+          click on the parent submit and see what got validated
+          hit reset to reset the validation values
+          do as many times as you wish :-)
+
+        A correct result would be that when the parent submit gets called the result is that both
+        the child form got validated as well as the parent form.
+      </p>
+      <h3>Form</h3>
+      <div>
+         <form wicket:id="parentForm">
+            <label>Name:
+              <input type="text" wicket:id="name"/>
+            </label>
+            <label>Company:
+              <input type="text" wicket:id="company"/>
+            </label>
+            <div wicket:id="addressInfo"></div>
+             <input type="button" wicket:id="parentSubmitBtn" value="Submit Parent Form"/>
+         </form>
+         <br/>
+         <br/>
+
+         <input type="button" wicket:id="resetSubmits" value="Reset Submissions"/>
+         <br/>
+         <br/>
+         <div wicket:id="validations">
+           <p>
+              <label>Parent Form Validated:<wicket:label wicket:id="parentValidated"/> </label>
+           </p>
+           <p>
+              <label>Child Form Validated: <wicket:label wicket:id="childValidated"/></label>
+           </p>
+         </div>
+      </div>
+    </div>
+    <div id="ft">
+    </div>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/wicket/blob/e193f4f4/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/OnFormValidateModelObjectsPage.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/OnFormValidateModelObjectsPage.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/OnFormValidateModelObjectsPage.java
new file mode 100644
index 0000000..514b4c0
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/onFormValidateModelObjects/OnFormValidateModelObjectsPage.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup.html.form.onFormValidateModelObjects;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.wicket.Session;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+import org.apache.wicket.markup.html.form.onFormValidateModelObjects.AddressFormPanel.ChildModel;
+
+/**
+ * Test page for <a href="https://issues.apache.org/jira/browse/WICKET-4344">WICKET-4344</a>
+ */
+public class OnFormValidateModelObjectsPage extends WebPage
+{
+	private static Map<String, ParentModel> pmMap = new HashMap<String, ParentModel>();
+
+	public OnFormValidateModelObjectsPage(final PageParameters parameters)
+	{
+		super(parameters);
+
+		CompoundPropertyModel<ParentModel> parentModel = new CompoundPropertyModel<ParentModel>(
+				new LoadableDetachableModel<ParentModel>()
+				{
+					@Override
+					protected ParentModel load()
+					{
+						String id = Session.get().getId();
+						ParentModel pm = pmMap.get(id);
+						if (pm == null)
+						{
+							pm = new ParentModel();
+							pmMap.put(id, pm);
+						}
+						return pm;
+					}
+				});
+
+		setDefaultModel(parentModel); // so we don't need to get it from the
+										// form.
+
+		Form parentForm = new Form("parentForm", parentModel)
+		{
+			@Override
+			protected void onValidateModelObjects()
+			{
+				super.onValidateModelObjects();
+
+				((ParentModel)getModelObject()).setParentValidated(true);
+			}
+		};
+		parentForm.add(new TextField("name"));
+		parentForm.add(new TextField("company"));
+		add(parentForm);
+
+		IModel<ChildModel> childModel = new CompoundPropertyModel(parentModel);
+		parentForm.add(new AddressFormPanel("addressInfo", (IModel<ChildModel>)childModel));
+
+		parentForm.add(new AjaxSubmitLink("parentSubmitBtn", parentForm)
+		{
+			@Override
+			protected void onSubmit(AjaxRequestTarget target, Form<?> form)
+			{
+				super.onSubmit(target, form);
+				target.add(getThePage().get("validations"));
+			}
+		});
+
+		add(new AjaxLink("resetSubmits")
+		{
+			@Override
+			public void onClick(AjaxRequestTarget target)
+			{
+				ParentModel pm = (ParentModel)getPage().getDefaultModelObject();
+				pm.setChildValidated(false);
+				pm.setParentValidated(false);
+
+				target.add(getThePage().get("validations"));
+			}
+		});
+
+		WebMarkupContainer cont = new WebMarkupContainer("validations");
+		cont.setOutputMarkupPlaceholderTag(true);
+		add(cont);
+		cont.add(new Label("parentValidated"));
+		cont.add(new Label("childValidated"));
+
+	}
+
+	private void handleChildSubmittedCalled(AjaxRequestTarget target)
+	{
+		target.add(get("validations"));
+	}
+
+	private OnFormValidateModelObjectsPage getThePage()
+	{
+		return this;
+	}
+
+	public class ParentModel extends AddressFormPanel.ChildModel
+	{
+		String name = "name";
+		String company = "company";
+
+		boolean parentValidated;
+
+		public ParentModel()
+		{
+			super();
+		}
+
+		public String getName()
+		{
+			return name;
+		}
+
+		public void setName(String name)
+		{
+			this.name = name;
+		}
+
+		public String getCompany()
+		{
+			return company;
+		}
+
+		public void setCompany(String company)
+		{
+			this.company = company;
+		}
+
+		public boolean isParentValidated()
+		{
+			return parentValidated;
+		}
+
+		public void setParentValidated(boolean parentValid)
+		{
+			this.parentValidated = parentValid;
+		}
+
+		@Override
+		public void submittedCalled(AjaxRequestTarget target)
+		{
+			handleChildSubmittedCalled(target);
+		}
+	}
+}