This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git


The following commit(s) were added to refs/heads/master by this push:
     new 21f42085a0 WICKET-7123 default form submit can now be set one per form 
(#971)
21f42085a0 is described below

commit 21f42085a02ebd1f82cf08425ea3645354ad6131
Author: Viliam Repan <[email protected]>
AuthorDate: Wed Oct 16 07:48:39 2024 +0200

    WICKET-7123 default form submit can now be set one per form (#971)
    
    * WICKET-7123 default form submit can now be set one per form (not form 
hierarchy)
    
    * WICKET-7123 fixed missing license header
    
    * WICKET-7123 removed jquery from form script
    
    * WICKET-7123 added example for default form submit used in form hierarchy
    
    * WICKET-7123 replaced wrong element (td)
    
    * WICKET-7123 Minor improvements to the example/demo page
    
    Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
    
    ---------
    
    Signed-off-by: Martin Tzvetanov Grigorov <[email protected]>
    Co-authored-by: Martin Tzvetanov Grigorov <[email protected]>
---
 .../form/FormDefaultButtonTestPage_expected.html   |   4 +-
 .../form/FormHierarchyDefaultButtonTestPage.html   |  16 ++
 .../form/FormHierarchyDefaultButtonTestPage.java   |  69 ++++++++
 ...ormHierarchyDefaultButtonTestPage_expected.html |  38 +++++
 .../apache/wicket/markup/html/form/FormTest.java   |   9 +
 .../org/apache/wicket/markup/html/form/Form.java   |  85 +++------
 .../wicket/examples/forminput/FormInput.html       |  54 +++++-
 .../wicket/examples/forminput/FormInput.java       | 189 +++++++++++++++++----
 .../wicket/examples/forminput/FormInput.properties |   9 +-
 .../apache/wicket/examples/forminput/forminput.css |  41 +++++
 10 files changed, 416 insertions(+), 98 deletions(-)

diff --git 
a/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormDefaultButtonTestPage_expected.html
 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormDefaultButtonTestPage_expected.html
index b108777d5d..ed32e337f6 100644
--- 
a/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormDefaultButtonTestPage_expected.html
+++ 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormDefaultButtonTestPage_expected.html
@@ -4,13 +4,13 @@
 <script type="text/javascript">
 /*<![CDATA[*/
 Wicket.Event.add(window, "domready", function(event) { 
-Wicket.Event.add('form2_hf_1', 'click', function(event) { var 
b=document.getElementById('default1'); if (b!=null && b.onclick!=null && 
typeof(b.onclick) != 'undefined') {  var r = Wicket.bind(b.onclick, b)(); if (r 
!= false) b.click(); } else { b.click(); };  return false;;});;
+Wicket.Event.add('form2', 'keypress', function(event) { var b = 
document.getElementById('default1');if (window.getComputedStyle(b).visibility 
=== 'hidden') return;if (event.which == 13) 
{event.stopPropagation();event.preventDefault();if (b != null && b.onclick != 
null && typeof (b.onclick) != 'undefined') {var r = Wicket.bind(b.onclick, 
b)();if (r != false) b.click();} else {b.click();}return false;};});;
 Wicket.Event.publish(Wicket.Event.Topic.AJAX_HANDLERS_BOUND);
 ;});
 /*]]>*/
 </script>
 </head><body>
-       <form wicket:id="form" id="form2" method="post" 
action="./org.apache.wicket.markup.html.form.FormDefaultButtonTestPage?0-1.-form"><div
 id="form2_hf_0" hidden="" class="hidden-fields"></div><div hidden="" 
class="hidden-fields"><input type="text" tabindex="-1" 
autocomplete="off"/><input id="form2_hf_1" type="submit" tabindex="-1" 
name="default" /></div>
+       <form wicket:id="form" id="form2" method="post" 
action="./org.apache.wicket.markup.html.form.FormDefaultButtonTestPage?0-1.-form"><div
 id="form2_hf_0" hidden="" class="hidden-fields"></div>
                <button wicket:id="default" name="default" 
id="default1"></button>
        </form>
 </body>
diff --git 
a/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormHierarchyDefaultButtonTestPage.html
 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormHierarchyDefaultButtonTestPage.html
new file mode 100644
index 0000000000..0cf9c61c7b
--- /dev/null
+++ 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormHierarchyDefaultButtonTestPage.html
@@ -0,0 +1,16 @@
+<html>
+<body>
+<form wicket:id="parentForm">
+
+    <input type="text" wicket:id="parentInput"/>
+
+    <button wicket:id="parentSubmit"></button>
+
+    <form wicket:id="childForm">
+        <input type="text" wicket:id="childInput"/>
+
+        <button wicket:id="childSubmit"></button>
+    </form>
+</form>
+</body>
+</html>
diff --git 
a/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormHierarchyDefaultButtonTestPage.java
 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormHierarchyDefaultButtonTestPage.java
new file mode 100644
index 0000000000..b9c9b3f518
--- /dev/null
+++ 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormHierarchyDefaultButtonTestPage.java
@@ -0,0 +1,69 @@
+/*
+ * 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 org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior;
+import org.apache.wicket.markup.html.WebPage;
+import org.junit.jupiter.api.Assertions;
+
+public class FormHierarchyDefaultButtonTestPage extends WebPage {
+    /**
+     * For serialization.
+     */
+    private static final long serialVersionUID = 1L;
+
+    public final Form<Void> parentForm;
+    public final Form<Void> childForm;
+    public final Button parentSubmit;
+    public final Button childSubmit;
+    public final TextField<?> parentInput;
+    public final TextField<?> childInput;
+
+    /**
+     * Construct.
+     */
+    public FormHierarchyDefaultButtonTestPage() {
+        parentForm = new Form<>("parentForm");
+        add(parentForm);
+
+        parentInput = new TextField<>("parentInput");
+        parentForm.add(parentInput);
+
+        parentSubmit = new Button("parentSubmit");
+        parentSubmit.add(new AjaxFormSubmitBehavior(parentForm, "click") {
+
+            @Override
+            protected void onSubmit(AjaxRequestTarget target) {
+                Assertions.fail("Shouldn't be called");
+            }
+
+        });
+        parentForm.setDefaultButton(parentSubmit);
+        parentForm.add(parentSubmit);
+
+        childForm = new Form<>("childForm");
+        parentForm.add(childForm);
+
+        childInput = new TextField<>("childInput");
+        childForm.add(childInput);
+
+        childSubmit = new Button("childSubmit");
+        childForm.setDefaultButton(childSubmit);
+        childForm.add(childSubmit);
+    }
+}
diff --git 
a/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormHierarchyDefaultButtonTestPage_expected.html
 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormHierarchyDefaultButtonTestPage_expected.html
new file mode 100644
index 0000000000..2cadec6515
--- /dev/null
+++ 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormHierarchyDefaultButtonTestPage_expected.html
@@ -0,0 +1,38 @@
+<html>
+<head><script type="text/javascript" 
src="../resource/org.apache.wicket.resource.JQueryResourceReference/jquery/jquery-3.7.1.js"></script>
+<script type="text/javascript" 
src="../resource/org.apache.wicket.ajax.AbstractDefaultAjaxBehavior/res/js/wicket-ajax-jquery.js"></script>
+<script type="text/javascript" id="wicket-ajax-debug-enable">
+/*<![CDATA[*/
+Wicket.Log.enabled=true;
+/*]]>*/
+</script>
+<script type="text/javascript" id="wicket-ajax-base-url">
+/*<![CDATA[*/
+Wicket.Ajax.baseUrl="wicket/bookmarkable/org.apache.wicket.markup.html.form.FormHierarchyDefaultButtonTestPage?0";
+/*]]>*/
+</script>
+<script type="text/javascript">
+/*<![CDATA[*/
+Wicket.Event.add(window, "domready", function(event) { 
+Wicket.Ajax.ajax({"u":"./org.apache.wicket.markup.html.form.FormHierarchyDefaultButtonTestPage?0-1.0-parentForm-parentSubmit","m":"POST","c":"parentSubmit2","f":"parentForm1","sc":"parentSubmit","e":"click"});;
+Wicket.Event.add('childForm4', 'keypress', function(event) { var b = 
document.getElementById('childSubmit3');if 
(window.getComputedStyle(b).visibility === 'hidden') return;if (event.which == 
13) {event.stopPropagation();event.preventDefault();if (b != null && b.onclick 
!= null && typeof (b.onclick) != 'undefined') {var r = Wicket.bind(b.onclick, 
b)();if (r != false) b.click();} else {b.click();}return false;};});;
+Wicket.Event.add('parentForm1', 'keypress', function(event) { var b = 
document.getElementById('parentSubmit2');if 
(window.getComputedStyle(b).visibility === 'hidden') return;if (event.which == 
13) {event.stopPropagation();event.preventDefault();if (b != null && b.onclick 
!= null && typeof (b.onclick) != 'undefined') {var r = Wicket.bind(b.onclick, 
b)();if (r != false) b.click();} else {b.click();}return false;};});;
+Wicket.Event.publish(Wicket.Event.Topic.AJAX_HANDLERS_BOUND);
+;});
+/*]]>*/
+</script>
+</head><body>
+<form wicket:id="parentForm" id="parentForm1" method="post" 
action="./org.apache.wicket.markup.html.form.FormHierarchyDefaultButtonTestPage?0-1.-parentForm"><div
 id="parentForm1_hf_0" hidden="" class="hidden-fields"></div>
+
+    <input type="text" wicket:id="parentInput" value="" name="parentInput"/>
+
+    <button wicket:id="parentSubmit" name="parentSubmit" 
id="parentSubmit2"></button>
+
+    <div wicket:id="childForm" id="childForm4">
+        <input type="text" wicket:id="childInput" value="" 
name="childForm:childInput"/>
+
+        <button wicket:id="childSubmit" name="childForm:childSubmit" 
id="childSubmit3"></button>
+    </div>
+</form>
+</body>
+</html>
diff --git 
a/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormTest.java
 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormTest.java
index 9994cda2a2..919bc8eddb 100644
--- 
a/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormTest.java
+++ 
b/wicket-core-tests/src/test/java/org/apache/wicket/markup/html/form/FormTest.java
@@ -65,6 +65,15 @@ public class FormTest extends WicketTestCase
                executeTest(FormDefaultButtonTestPage.class, 
"FormDefaultButtonTestPage_expected.html");
        }
 
+       /**
+        * WICKET-7123
+        */
+       @Test
+       void defaultButtonHierarchy() throws Exception
+       {
+               executeTest(FormHierarchyDefaultButtonTestPage.class, 
"FormHierarchyDefaultButtonTestPage_expected.html");
+       }
+
        /**
         * WICKET-6525 / WICKET-6348
         */
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 fb0ab15362..8e80799c53 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
@@ -1098,16 +1098,7 @@ public class Form<T> extends WebMarkupContainer
        }
 
        /**
-        * Sets the default IFormSubmittingComponent. If set (not null), a 
hidden submit component will
-        * be rendered right after the form tag, so that when users press enter 
in a textfield, this
-        * submit component's action will be selected. If no default component 
is set (so unset by
-        * calling this method with null), nothing additional is rendered.
-        * <p>
-        * WARNING: note that this is a best effort only. Unfortunately having 
a 'default' button in a
-        * form is ill defined in the standards, and of course IE has it's own 
way of doing things.
-        * </p>
-        * There can be only one default button per form hierarchy. So if you 
set default button on a
-        * nested form, it will actually delegate the call to root form. </b>
+        * Sets the default IFormSubmittingComponent.
         *
         * @param submittingComponent
         *            The component to set as the default submitting component, 
or null when you want to
@@ -1115,14 +1106,7 @@ public class Form<T> extends WebMarkupContainer
         */
        public final void setDefaultButton(IFormSubmittingComponent 
submittingComponent)
        {
-               if (isRootForm())
-               {
-                       defaultSubmittingComponent = submittingComponent;
-               }
-               else
-               {
-                       getRootForm().setDefaultButton(submittingComponent);
-               }
+               defaultSubmittingComponent = submittingComponent;
        }
 
        /**
@@ -1266,58 +1250,44 @@ public class Form<T> extends WebMarkupContainer
        }
 
        /**
-        * If a default IFormSubmittingComponent was set on this form, this 
method will be called to
-        * render an extra field with an invisible style so that pressing enter 
in one of the textfields
-        * will do a form submit using this component. This method is 
overridable as what we do is best
-        * effort only, and may not what you want in specific situations. So if 
you have specific
-        * usability concerns, or want to follow another strategy, you may 
override this method.
+        * If a default IFormSubmittingComponent was set on this form, this 
method will be called and
+        * can be used to render extra items to HTML.
         *
         * @see #addDefaultSubmitButtonHandler(IHeaderResponse)
         */
+       @Deprecated
        protected void appendDefaultButtonField()
        {
-               AppendingStringBuffer buffer = new AppendingStringBuffer();
-
-               // hidden div
-               buffer.append(String.format("<div hidden=\"\" class=\"%s\">",
-                       getString(HIDDEN_FIELDS_CSS_CLASS_KEY)));
-
-               // add an empty textfield (otherwise IE doesn't work)
-               buffer.append("<input type=\"text\" tabindex=\"-1\" 
autocomplete=\"off\"/>");
-
-               // add the submitting component
-               buffer
-                       .append(String.format("<input id=\"%s\" type=\"submit\" 
tabindex=\"-1\" name=\"%s\" />",
-                               getHiddenFieldsId(HIDDEN_FIELDS_SUBMIT_IDX),
-                               defaultSubmittingComponent.getInputName()));
-
-               // close div
-               buffer.append("</div>");
-
-               getResponse().write(buffer);
+               // intentionally left empty for backward compatibility
        }
 
        /**
-        * Where {@link #appendDefaultButtonField()} renders the markup for 
default submit button
-        * handling, this method attaches the event handler to its 'click' 
event. The 'click' event on
-        * the hidden submit button will be dispatched to the selected default 
submit button. As with
-        * {@link #appendDefaultButtonField()} this method can be overridden 
when the generated code
-        * needs to be adjusted for a specific usecase.
+        * This method attaches the event handler to its 'enter' event.
         *
         * @param headerResponse
         *            The header response.
         */
        protected void addDefaultSubmitButtonHandler(IHeaderResponse 
headerResponse)
        {
-               final Component submittingComponent = (Component) 
defaultSubmittingComponent;
-               AppendingStringBuffer buffer = new AppendingStringBuffer();
-               buffer.append("var b=document.getElementById('");
-               buffer.append(submittingComponent.getMarkupId());
-               buffer.append("'); if (b!=null && b.onclick!=null && 
typeof(b.onclick) != 'undefined') ");
-               buffer.append(
-                       "{  var r = Wicket.bind(b.onclick, b)(); if (r != 
false) b.click(); } else { b.click(); };  return false;");
-               headerResponse.render(OnEventHeaderItem
-                       
.forMarkupId(getHiddenFieldsId(HIDDEN_FIELDS_SUBMIT_IDX), "click", 
buffer.toString()));
+               final Component component = (Component) 
defaultSubmittingComponent;
+               String submitId = component.getMarkupId();
+
+               AppendingStringBuffer script = new AppendingStringBuffer();
+               script.append("var b = 
document.getElementById('").append(submitId).append("');");
+               script.append("if (window.getComputedStyle(b).visibility === 
'hidden') return;");
+               script.append("if (event.which == 13) {");
+               script.append("event.stopPropagation();");
+               script.append("event.preventDefault();");
+               script.append("if (b != null && b.onclick != null && typeof 
(b.onclick) != 'undefined') {");
+               script.append("var r = Wicket.bind(b.onclick, b)();");
+               script.append("if (r != false) b.click();");
+               script.append("} else {");
+               script.append("b.click();");
+               script.append("}");
+               script.append("return false;");
+               script.append("}");
+
+               
headerResponse.render(OnEventHeaderItem.forMarkupId(getMarkupId(), "keypress", 
script.toString()));
        }
 
        /**
@@ -1792,8 +1762,7 @@ public class Form<T> extends WebMarkupContainer
        }
 
        /**
-        * Writes the markup for the hidden input fields and default button 
field if applicable to the
-        * current response.
+        * Writes the markup for the hidden input fields if applicable to the 
current response.
         */
        public final void writeHiddenFields()
        {
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.html
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.html
index d8e7c4fcfe..86a914e443 100644
--- 
a/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.html
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.html
@@ -1,4 +1,21 @@
-<html xmlns:wicket="http://wicket.apache.org";>
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<html xmlns:wicket="http://wicket.apache.org"; 
xmlns="http://www.w3.org/1999/html";>
 <wicket:head>
     <title>Wicket Examples - forminput</title>
 </wicket:head>
@@ -81,6 +98,41 @@
        <div id="feedbackPanel">
                <span wicket:id="feedback"/>
     </div>
+
+       <h2 class="example-title"><wicket:message 
key="FormInput.formHierarchyExample"/></h2>
+
+       <form wicket:id="parentForm" class="parent-form">
+               <h3><wicket:message key="FormInput.parentForm"/></h3>
+
+               <div class="gap-1">
+                       <label for="parentText"><wicket:message 
key="FormInput.parentTextLabel"/></label>
+                       <input type="text" wicket:id="parentText" 
id="parentText"/>
+                       <input type="submit" wicket:id="parentSubmit" 
wicket:message="value:FormInput.parentSubmit"/>
+               </div>
+
+               <form wicket:id="childForm" class="child-form">
+                       <h3><wicket:message key="FormInput.childForm"/></h3>
+
+                       <div class="gap-1">
+                               <label for="childText"><wicket:message 
key="FormInput.childTextLabel"/></label>
+                               <input type="text" wicket:id="childText" 
id="childText"/>
+                               <input type="submit" wicket:id="childSubmit" 
wicket:message="value:FormInput.childSubmit"/>
+                       </div>
+               </form>
+
+               <div wicket:id="parentFormDataTable" class="parent-data-table">
+                       <h3><wicket:message key="FormInput.submittedData"/></h3>
+                       <div class="gap-1">
+                               <wicket:message 
key="FormInput.parentTextLabel"/>
+                               <span wicket:id="parentData"/>
+                       </div>
+                       <div class="gap-1">
+                               <wicket:message key="FormInput.childTextLabel"/>
+                               <span wicket:id="childData"/>
+                       </div>
+               </div>
+       </form>
+
 </wicket:extend>
 </body>
 </html>
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.java
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.java
index b2e5fd8152..f077da2948 100644
--- 
a/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.java
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.java
@@ -16,45 +16,42 @@
  */
 package org.apache.wicket.examples.forminput;
 
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
+import org.apache.wicket.event.IEvent;
 import org.apache.wicket.examples.WicketExamplePage;
+import org.apache.wicket.markup.head.CssHeaderItem;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Button;
-import org.apache.wicket.markup.html.form.Check;
-import org.apache.wicket.markup.html.form.CheckBox;
-import org.apache.wicket.markup.html.form.CheckGroup;
-import org.apache.wicket.markup.html.form.DropDownChoice;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.form.FormComponentUpdatingBehavior;
-import org.apache.wicket.markup.html.form.IChoiceRenderer;
-import org.apache.wicket.markup.html.form.ListMultipleChoice;
-import org.apache.wicket.markup.html.form.Radio;
-import org.apache.wicket.markup.html.form.RadioChoice;
-import org.apache.wicket.markup.html.form.RadioGroup;
-import org.apache.wicket.markup.html.form.SimpleFormComponentLabel;
-import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.form.*;
 import org.apache.wicket.markup.html.link.Link;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.markup.html.panel.FeedbackPanel;
 import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.request.http.WebRequest;
+import org.apache.wicket.request.resource.CssResourceReference;
 import org.apache.wicket.util.convert.ConversionException;
 import org.apache.wicket.util.convert.IConverter;
 import org.apache.wicket.util.convert.MaskConverter;
 import org.apache.wicket.validation.validator.RangeValidator;
 
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
 
 /**
  * Example for form input.
- * 
+ *
  * @author Eelco Hillenius
  * @author Jonathan Locke
  */
@@ -67,9 +64,9 @@ public class FormInput extends WicketExamplePage
        {
                /**
                 * Construct.
-                * 
+                *
                 * @param name
-                *            Component name
+                *      Component name
                 */
                @SuppressWarnings("serial")
                public InputForm(String name)
@@ -80,9 +77,11 @@ public class FormInput extends WicketExamplePage
                        add(new LocaleDropDownChoice("localeSelect"));
 
                        // Link to return to default locale
-                       add(new Link<Void>("defaultLocaleLink") {
-                               public void onClick() {
-                                       WebRequest request = 
(WebRequest)getRequest();
+                       add(new Link<Void>("defaultLocaleLink")
+                       {
+                               public void onClick()
+                               {
+                                       WebRequest request = (WebRequest) 
getRequest();
                                        setLocale(request.getLocale());
                                }
                        });
@@ -177,7 +176,8 @@ public class FormInput extends WicketExamplePage
 
                        add(new Button("saveButton"));
 
-                       add(new Button("resetButton") {
+                       add(new Button("resetButton")
+                       {
                                @Override
                                public void onSubmit()
                                {
@@ -194,12 +194,14 @@ public class FormInput extends WicketExamplePage
                }
        }
 
-       /** list view to be nested in the form. */
+       /**
+        * list view to be nested in the form.
+        */
        private static final class LinesListView extends ListView<String>
        {
                /**
                 * Construct.
-                * 
+                *
                 * @param id
                 */
                public LinesListView(String id)
@@ -238,9 +240,9 @@ public class FormInput extends WicketExamplePage
        {
                /**
                 * Construct.
-                * 
+                *
                 * @param id
-                *            component id
+                *      component id
                 */
                public LocaleDropDownChoice(String id)
                {
@@ -249,8 +251,9 @@ public class FormInput extends WicketExamplePage
                        // set the model that gets the current locale, and that 
is used for
                        // updating the current locale to property 'locale' of 
FormInput
                        setModel(new PropertyModel<>(FormInput.this, "locale"));
-                       
-                       add(new FormComponentUpdatingBehavior() {
+
+                       add(new FormComponentUpdatingBehavior()
+                       {
                                @Override
                                protected void onUpdate()
                                {
@@ -280,16 +283,39 @@ public class FormInput extends WicketExamplePage
        public FormInput()
        {
                // Construct form and feedback panel and hook them up
-               final FeedbackPanel feedback = new FeedbackPanel("feedback");
+               final FeedbackPanel feedback = new FeedbackPanel("feedback")
+               {
+                       @Override
+                       public void onEvent(IEvent<?> event) {
+                               final Object payload = event.getPayload();
+                               if (payload instanceof 
IPartialPageRequestHandler)
+                               {
+                                       ((IPartialPageRequestHandler) 
payload).add(this);
+                               }
+                       }
+               };
+               feedback.setOutputMarkupId(true);
                add(feedback);
                add(new InputForm("inputForm"));
+
+               IModel<ParentFormData> model = Model.of(new ParentFormData());
+
+               add(new ParentForm("parentForm", model));
+       }
+
+       @Override
+       public void renderHead(IHeaderResponse response)
+       {
+               super.renderHead(response);
+               response.render(
+                       CssHeaderItem.forReference(new 
CssResourceReference(FormInput.class, "forminput.css")));
        }
 
        /**
         * Sets locale for the user's session (getLocale() is inherited from 
Component)
-        * 
+        *
         * @param locale
-        *            The new locale
+        *      The new locale
         */
        public void setLocale(Locale locale)
        {
@@ -322,4 +348,95 @@ public class FormInput extends WicketExamplePage
                        return value != null ? value.toString() : null;
                }
        }
+
+       private static class ParentForm extends Form<ParentFormData>
+       {
+
+               public ParentForm(String id, IModel<ParentFormData> model)
+               {
+                       super(id);
+
+                       TextField<String> parentText = new 
TextField<>("parentText", new PropertyModel<>(model, "parentText"));
+                       add(parentText);
+
+                       final ParentFormDataTable parentFormDataTable = new 
ParentFormDataTable("parentFormDataTable", model);
+                       add(parentFormDataTable);
+
+                       AjaxSubmitLink parentSubmit = new 
AjaxSubmitLink("parentSubmit")
+                       {
+
+                               @Override
+                               protected void onSubmit(AjaxRequestTarget 
target)
+                               {
+                                       info("Parent form submitted");
+
+                                       target.add(parentFormDataTable);
+                               }
+                       };
+                       add(parentSubmit);
+                       setDefaultButton(parentSubmit);
+
+                       Form<Void> childForm = new Form<>("childForm");
+                       add(childForm);
+
+                       TextField<String> childText = new 
TextField<>("childText", new PropertyModel<>(model, "childText"));
+                       childForm.add(childText);
+
+                       AjaxSubmitLink childSubmit = new 
AjaxSubmitLink("childSubmit")
+                       {
+
+                               @Override
+                               protected void onSubmit(AjaxRequestTarget 
target)
+                               {
+                                       info("Child form submitted");
+
+                                       target.add(parentFormDataTable);
+                               }
+                       };
+                       childForm.add(childSubmit);
+                       childForm.setDefaultButton(childSubmit);
+               }
+       }
+
+       private static final class ParentFormDataTable extends 
WebMarkupContainer
+       {
+
+               public ParentFormDataTable(String id, IModel<ParentFormData> 
model)
+               {
+                       super(id);
+
+                       setOutputMarkupId(true);
+
+                       add(new Label("parentData", new PropertyModel<>(model, 
"parentText")));
+                       add(new Label("childData", new PropertyModel<>(model, 
"childText")));
+               }
+       }
+
+       private static class ParentFormData implements Serializable
+       {
+
+               private String parentText;
+
+               private String childText;
+
+               public String getParentText()
+               {
+                       return parentText;
+               }
+
+               public void setParentText(String parentText)
+               {
+                       this.parentText = parentText;
+               }
+
+               public String getChildText()
+               {
+                       return childText;
+               }
+
+               public void setChildText(String childText)
+               {
+                       this.childText = childText;
+               }
+       }
 }
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.properties
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.properties
index 26fe822127..b3fb668591 100644
--- 
a/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.properties
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/FormInput.properties
@@ -30,4 +30,11 @@ select.one.or.more.numbers=select one or more numbers
 your.favorite.sites=your favorite sites
 save=Save
 reset=Reset
-
+FormInput.parentTextLabel=Parent text field:
+FormInput.childTextLabel=Child text field:
+FormInput.parentSubmit=Submit parent form
+FormInput.childSubmit=Submit child form
+FormInput.submittedData=Submitted form data
+FormInput.formHierarchyExample=Example of form hierarchy with default submit 
buttons
+FormInput.parentForm=Parent form
+FormInput.childForm=Child form
\ No newline at end of file
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/forminput.css
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/forminput.css
new file mode 100644
index 0000000000..3d0e373dfa
--- /dev/null
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/forminput/forminput.css
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+.parent-form {
+    padding: 0.5rem;
+    border: 1px solid gray;
+}
+
+.child-form {
+    margin-top: 2rem;
+    padding: 0.5rem;
+    border: 1px solid gray;
+}
+
+.gap-1 {
+    display: flex;
+    gap: 0.5rem
+}
+
+.parent-data-table {
+    margin-top: 2rem;
+}
+
+.example-title {
+    margin-top: 4rem;
+    margin-bottom: 0.5rem;
+}
\ No newline at end of file

Reply via email to