Skip to content

Commit

Permalink
WICKET-7123 default form submit can now be set one per form (#971)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
1azyman and martin-g authored Oct 16, 2024
1 parent c381a60 commit 21f4208
Show file tree
Hide file tree
Showing 10 changed files with 416 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ void defaultButton() throws Exception
executeTest(FormDefaultButtonTestPage.class, "FormDefaultButtonTestPage_expected.html");
}

/**
* WICKET-7123
*/
@Test
void defaultButtonHierarchy() throws Exception
{
executeTest(FormHierarchyDefaultButtonTestPage.class, "FormHierarchyDefaultButtonTestPage_expected.html");
}

/**
* WICKET-6525 / WICKET-6348
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1098,31 +1098,15 @@ public void component(final Component component, final IVisit<Void> visit)
}

/**
* 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
* 'unset' any previously set default component
*/
public final void setDefaultButton(IFormSubmittingComponent submittingComponent)
{
if (isRootForm())
{
defaultSubmittingComponent = submittingComponent;
}
else
{
getRootForm().setDefaultButton(submittingComponent);
}
defaultSubmittingComponent = submittingComponent;
}

/**
Expand Down Expand Up @@ -1266,58 +1250,44 @@ public void component(final FormComponent<?> formComponent, IVisit<Void> visit)
}

/**
* 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()));
}

/**
Expand Down Expand Up @@ -1792,8 +1762,7 @@ public void renderHead(IHeaderResponse response)
}

/**
* 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()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -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>
Loading

0 comments on commit 21f4208

Please sign in to comment.