Feedback panel added but does not show all messages - wicket

I have some basic form when you type email, old password, new password and repeat new pass for your profile modify. What I'm trying to achive is to display feedback msg when pass is wrong. A piece of code looks like this:
public class EditProfileForm extends Form<Void>
{
private static final long serialVersionUID = 1L;
// El-cheapo model for form
private final ValueMap properties = new ValueMap();
private ModalWindow modalWindow;
#SpringBean
UserManager userManager;
#SpringBean
Validator validator;
private User user;
private static final String EMAIL = "mp-email";
private static final String OLD_PASS = "mp-oldpass";
private static final String NEW_PASS = "mp-newpass";
private static final String NEW_PASS_REPEAT = "mp-newpassrepeat";
private static final String ERROR_WRONG_PASS = "Wrong pass";
private static final String ERROR_PASS_DIFF = "Pass diff";
private static final String ERROR_EMAIL_INVALID = "Wrong email";
private static final String ERROR_EMAIL_EXISTS = "Email used";
public EditProfileForm( String id, final ModalWindow modalWindow,final User u )
{
super( id );
this.user = u;
this.modalWindow = modalWindow;
add( new TextField<String>( EMAIL, new PropertyModel<String>( properties, EMAIL ) ).setRequired(true).setOutputMarkupId(true) );
add( new PasswordTextField( OLD_PASS, new PropertyModel<String>( properties, OLD_PASS ) ).setOutputMarkupId(true) );
add( new PasswordTextField( NEW_PASS, new PropertyModel<String>( properties, NEW_PASS ) ).setOutputMarkupId(true) );
add( new PasswordTextField( NEW_PASS_REPEAT, new PropertyModel<String>( properties, NEW_PASS_REPEAT ) ).setOutputMarkupId(true) );
final FeedbackPanel feedbackPanel = new FeedbackPanel( "feedback" );
feedbackPanel.setOutputMarkupId( true );
//feedbackPanel.setMaxMessages( 5 );
add( feedbackPanel );
AjaxSubmitLink closeBtn = new AjaxCloseCancelBtn( "close-x", this );
AjaxSubmitLink cancelBtn = new AjaxCloseCancelBtn( "cancel", this );
add( new AjaxSubmitLink( "save", this )
{
private static final long serialVersionUID = 1L;
#Override
protected void onSubmit( AjaxRequestTarget target, Form<?> form )
{
if ( !user.getCryptedPassword().equals( CypherUtil.encodeMd5( getOldPassword() ) ) )
{
error( ERROR_WRONG_PASS );
}
else if ( !getNewPassword().equals( getNewPasswordRepeat() ) )
{
error( ERROR_PASS_DIFF );
}
else if ( !validator.validateEmailFormat( getEmail() ) )
{
error( ERROR_EMAIL_INVALID );
}
else if ( validator.emailExists( getEmail() ) )
{
error( ERROR_EMAIL_EXISTS );
} else
{
//save user data
}
}
#Override
protected void onError( AjaxRequestTarget target, Form<?> form )
{
target.add( feedbackPanel );
}
} );
add( closeBtn );
add( cancelBtn );
}
/**
* #return
*/
private String getEmail()
{
return properties.getString( EMAIL );
}
/**
* #return
*/
private String getOldPassword()
{
return properties.getString( OLD_PASS );
}
/**
* #return
*/
private String getNewPassword()
{
return properties.getString( NEW_PASS );
}
/**
* #return
*/
private String getNewPasswordRepeat()
{
return properties.getString( NEW_PASS_REPEAT );
}
}
Now when I leave these forms empty, I receive nice feedback msg that there fields are required. Meanwhile, when I type wrong pass, email or whatever I got nothing, and my server log leaves msg like this:
WARNING: Component-targetted feedback message was left unrendered.
This could be because you are missing a FeedbackPanel on the page.
Message: [FeedbackMessage message = "Wrong pass", reporter = save, level = ERROR]
The form is within a WebPage which is a popup:
public class ProfilePopup extends WebPage
{
private static final long serialVersionUID = 2929269801026361184L;
public ProfilePopup(final ModalWindow modal, final User user)
{
add( new EditProfileForm("profileModifyForm", modal, user).setOutputMarkupId(true) );
}
}
and HTML, placing feedback outside the form didn't help either :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body class="stats-popup-body">
<div class="stats-popup" id="car-info-edit-popup">
<p class="popup_title"> Edytuj Profilu </p>
<form wicket:id="profileModifyForm" class="stats-popup-form">
<div>
<label class="popup_field_label">Email:</label>
<input type="text" wicket:id="mp-email" />
</div>
<div class="clear9"></div>
<div>
<label class="popup_field_label">Stare hasło:</label>
<input type="password" name="E-mail" title="E-mail1" id="E-mail2" wicket:id="mp-oldpass" />
</div>
<div>
<label class="popup_field_label">Nowe hasło:</label>
<input type="password" wicket:id="mp-newpass" />
</div>
<div>
<label class="popup_field_label">Powtórz nowe hasło:</label>
<input type="password" wicket:id="mp-newpassrepeat" />
</div>
<span wicket:id="feedback"></span>
<div class="button-box-bottom">
<input class="btn btn_save" style="margin-right: 9px;"
wicket:id="save" type="button" value="Zapisz"
onmousemove="this.className='btn btn_save btn_hover'"
onmouseout="this.className='btn btn_save'" />
<input
class="btn btn_cancel" wicket:id="cancel"
value="Anuluj" type="button"
onmousemove="this.className='btn btn_cancel btn_hover'"
onmouseout="this.className='btn btn_cancel'" />
</div>
<div class="stats-popup-close-x" wicket:id="close-x"></div>
</form>
</div>
</body>
</html>

It's bad practice to perform input validations in onSubmit, because once you get there, (invalid) input has reached the Models. As you already are experiencing, onSubmit is invoked after the validation phase has ended, so the input will be considered valid, and therefore Form.onError will not be invoked.
Use a FormValidator instead (add an IFormValidator to the Form in your constructor), if you require to perform not so simple validations or validations that involve two or more components' inputs. Remember that user input will have not reached the component's Models in FormValidator.validate(), so you'll need to use Component.getConvertedInput() to get the input to be validated.
If your validations involve only one component, and operate only over its input, it might be recommendable to use an IValidator instead.
Also, notice that Wicket provides validators that perform some of the validations you'd like to perform: EqualPasswordInputValidator and EmailAddressValidator can be useful to you.
For instance:
emailField.add(EmailAddressValidator.getInstance());
form.add(new EqualPasswordInputValidator(passwordField, passwordRepeatField));
Take a look at this (somewhat outdated) wiki page for information on FormValidators: Validating related fields

Related

MVC4 custom remote validator message appears, but is ignored at form submit

I have an MVC4 registration form that employs two custom remote validators. The first validator checks for email uniqueness, and works properly. The second checks number of uses for a voucher code. It correctly displays a message after entering a voucher code, but it fails to honor the custom remote validation at the point of submission.
In other words, you can enter a voucher code and see the "Cannot use voucher..." message from the remote validator. But you can still submit the form.
This is the abbreviated markup for the form, with just the relevant fields and the submit button. The full form is much larger. The email fields, which use custom validation successfully, are retained in this example for comparison. You can see the RegistrationVoucherCode field and validator near the end of the form.
#using (Html.BeginForm("Index", "Registration", FormMethod.Post))
{
<div class="row">
<div class="col-lg-6 col-md-6 col-xs-6 field_wrapper">
<div class="form_label">#Html.LabelFor(m => m.EmailAddress)</div>
<div class="form_field">#Html.TextBoxFor(m => m.EmailAddress)</div>
<div class="form_validator">#Html.ValidationMessageFor(m => m.EmailAddress)</div>
</div>
<div class="col-lg-6 col-md-6 col-xs-6 field_wrapper">
<div class="form_label">Confirm Email</div>
<div class="form_field">#Html.TextBoxFor(m => m.ConfirmEmail)</div>
<div class="form_validator">#Html.ValidationMessageFor(m => m.ConfirmEmail)</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-6 col-xs-6 field_wrapper">
<div class="form_label">#Html.LabelFor(m => m.RegistrationVoucherCode)</div>
#{
string displayVoucherCode = Model.RegistrationVoucherCode.ToString();
if (Model.RegistrationVoucherCode == 0)
{
displayVoucherCode = string.Empty;
}
}
<div class="form_field">#Html.TextBoxFor(m => m.RegistrationVoucherCode, new { Value = displayVoucherCode, maxlength = 7 })</div>
<div class="form_validator">#Html.ValidationMessageFor(m => m.RegistrationVoucherCode)</div>
</div>
<div class="col-lg-6 col-md-6 col-xs-6 field_wrapper">
</div>
</div>
<div class="row">
<div class="col-xs-12">
<input type="submit" id="submitForm" value="Next" class="standard_button right_button" />
</div>
</div>
}
This is related code from my ProfileModel. The full model is much larger, so only relevant code is presented here. At the end of this you can see RegistrationVoucherCode.
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace SW.CEA.WebSite.Models.Registration
{
public class ProfileModel
{
public ProfileModel()
{
}
public Profile Profile { get; set; }
[Required(ErrorMessage = "Confirm Email is required.")]
[Display(Name = "Confirm Email")]
[StringLength(128)]
[RegularExpression(#"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "Confirm Email Address is Not Valid")]
[System.Web.Mvc.Compare("EmailAddress", ErrorMessage = "Email addresses do not match..")]
public string ConfirmEmail
{
get
{
return Profile.ConfirmEmail;
}
set
{
Profile.ConfirmEmail = value;
}
}
[Required(ErrorMessage = "Email Address is required.")]
[Display(Name = "Email")]
[StringLength(128)]
[Remote("ValidateEmailUniqueness", "Registration")]
[RegularExpression(#"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "Email Address is Not Valid")]
public string EmailAddress
{
get
{
return Profile.EmailAddress;
}
set
{
Profile.EmailAddress = value;
}
}
[Required(ErrorMessage = "Order Code is required.")]
[Display(Name = "Order Code")]
[Remote("ValidateVoucherCode", "Registration")]
public int RegistrationVoucherCode
{
get
{
return Profile.RegistrationVoucherCode;
}
set
{
Profile.RegistrationVoucherCode = value;
}
}
}
}
And these are custom validators from my RegistrationController. Again, email address validators appear here for comparison. My problem is with enforcing the ValidateVoucherCode custom validator at the point of form submission.
private bool IsEmailUnique(string EmailAddress)
{
var profile = ProfileRepository.GetProfile(EmailAddress);
return (profile == null);
}
[HttpGet]
public JsonResult ValidateEmailUniqueness(string EmailAddress)
{
if (!IsEmailUnique(EmailAddress))
{
return Json("Error, email address is already registered, please sign in.", JsonRequestBehavior.AllowGet);
}
return Json(true, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public JsonResult ValidateVoucherCode(int RegistrationVoucherCode)
{
var voucher = VoucherRepository.GetVoucherWithProfiles(RegistrationVoucherCode);
if (voucher == null)
{
return Json("Invalid Order Code", JsonRequestBehavior.AllowGet);
}
if (voucher.Profiles.Count >= Settings.Default.MaxVoucherUses)
{
return Json("Cannot user voucher, will exceed maximum number of voucher uses.", JsonRequestBehavior.AllowGet);
}
return Json(true, JsonRequestBehavior.AllowGet);
}
The message, "Cannot user voucher, will exceed maximum number of voucher uses," will successfully appear on the client in this ValidationMessageFor when an overused validation code is entered. This again is from the form.
#Html.TextBoxFor(m => m.RegistrationVoucherCode, new { Value = displayVoucherCode, maxlength = 7 })
#Html.ValidationMessageFor(m => m.RegistrationVoucherCode)
Upon tabbing off the form field, debugger shows this remote validator being hit.
[HttpGet]
public JsonResult ValidateVoucherCode(int RegistrationVoucherCode)
So the ValidateVoucherCode custom validator is doing part of it's job. It's showing the "Cannot use voucher..." message when I tab off the field. But it doesn't prevent the form from being submitted. By contrast, the unique email address validator on the same form will prevent form submission. I need the RegistrationVoucherCode validator to operate in the same manner. Thanks for your help.
The solution was to replace jquery-2.1.0.min.js with https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js.
The scripts that my form presently uses are:
https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js
jquery.validate.min.js
jquery.validate.unobtrusive.min.js

Wicket submit action doesn't work

After updating Wicket from version 6.12 to 6.13/6.14 onSubmit action doesn't work. For Example class:
public class LoginPage extends WebPage {
private String username = "";
private String password = "";
public LoginPage() {
super();
Form<?> form = new Form<Void>("form");
setDefaultModel(new CompoundPropertyModel<>(this));
form.add(new Button("submit") {
#Override
public void onSubmit() {
System.out.println("SUBMIT "+username+":"+password);
}
});
form.add(new TextField<String>("username").setRequired(true));
form.add(new PasswordTextField("password").setRequired(true));
add(form);
}
}
with HTML:
<!DOCTYPE html>
<html xmlns:wicket>
<body>
<form wicket:id="form">
<input id="name" type="text" placeholder="Username" wicket:id="username">
<input id="password" type="password" placeholder="Password" wicket:id="password">
<input type="submit" wicket:id="submit" value="Enter">
</form>
</body>
</html>
doesn't works with wicket version 6.13+ and great work with wicket 6.12-. Changing Button on something like SubmitLink doesn't help.
Could you tell me what's wrong?
Well... hacky but it seems to work with 6.15.
Replace encodePageComponentInfo with the following one.
#Override
protected void encodePageComponentInfo(Url url, PageComponentInfo info) {
Args.notNull(url, "url");
if (info != null) {
String s = info.toString();
if (!Strings.isEmpty(s)) {
try {
Integer.parseInt(s);
} catch (Exception e) {
QueryParameter parameter = new QueryParameter(s, "");
url.getQueryParameters().add(parameter);
}
}
}
}
I found problem in my test project. I use changed MountedMapper for hiding version number in the URL:
/**
* Wrapper for hiding the version number in the URL
*/
public class SimpleMountedMapper extends MountedMapper {
public SimpleMountedMapper(String mountPath, Class<? extends IRequestablePage> pageClass) {
super(mountPath, pageClass, new PageParametersEncoder());
}
#Override
protected void encodePageComponentInfo(Url url, PageComponentInfo info) {
}
public Url mapHandler(IRequestHandler requestHandler) {
if (requestHandler instanceof ListenerInterfaceRequestHandler) {
return null;
} else {
return super.mapHandler(requestHandler);
}
}
}
In new version of wicket something wrong with this implementation (got it from this question).

How would one use a [Wicket] ListView with a form?

I have added a Form on submit of which I have to add more wicket controls like Labels, textfields and button with an Ajex Link. But not able to get the correct HTML. Can anyone please help me to get rid of it ?
voucherPanel.html
<html xmlns:wicket>
<head>
</head>
<body>
<wicket:panel>
<div class="form-block">
<div wicket:id="form">
<wicket:message key="lbl.vouchercode" />
<div wicket:id="list">
<input wicket:id="word" type="text" />
</div>
<div wicket:id="vouchercode"></div>
<button wicket:id="submit"><wicket:message key="submitText"/></button>
</div>
</div>
</wicket:panel>
</body>
</html>
voucherPanel.java
public class VoucherPanel extends Panel
{
private static final long serialVersionUID = 1L;
public VoucherPanel(final String id)
{
super(id);
final TextField<String> voucherCodeField = new TextField<String>("vouchercode", Model.of(""));
voucherCodeField.setRequired(true);
final Button button = new Button("submit");
Form<?> form = new Form<Void>("form")
{
#Override
protected void onSubmit()
{
numberOfFields = new ArrayList<String>();
int noOfVocuhers = getNoOfAllowedVoucher();// just returing the number
for (int i = 0; i < noOfVocuhers; i++) {
numberOfFields.add(new String(""));
}
add(new ListView<Object>("list", numberOfFields) {
private static final long serialVersionUID = 1L;
#Override
protected void populateItem(ListItem<Object> item) {
final String word = (String) item.getModelObject();
System.out.println( "word =" +word );
TextField<String> textField = new TextField<String>("word", Model.of(""));
textField.setOutputMarkupId(true);
item.add(textField);
}
});
}
}
};
add(form);
form.add(voucherCodeField);
form.add(button);
}
}
You're trying to assign a Textfield to a <div> element (voucherCode), you need <input type="text"> instead.
You need to add list to your form right away, onSubmit is too late. Just set it outside, similar to button and call myListView.setList when submitting the form.
These are the two things I spotted... if you still have problems please let us know about the error messages you get.

Phonegap Screen-orientation plugin update for 2.7.0 or 2.8.0

Is there anybody out there, who knows how to fix this plugin to work with the newest cordova/phonegap version?
I have no idea how i can fix the errors in eclipse and i really need a method to change orientation for several pages in my phonegap app!
You need to make the following changes:
ScreenOrientation.java
Replace with this:
package com.tsukurusha.phonegap.plugins;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
public class ScreenOrientation extends CordovaPlugin {
// Refer to http://developer.android.com/reference/android/R.attr.html#screenOrientation
private static final String UNSPECIFIED = "unspecified";
private static final String LANDSCAPE = "landscape";
private static final String PORTRAIT = "portrait";
private static final String USER = "user";
private static final String BEHIND = "behind";
private static final String SENSOR = "sensor";
private static final String NOSENSOR = "nosensor";
private static final String SENSOR_LANDSCAPE = "sensorLandscape";
private static final String SENSOR_PORTRAIT = "sensorPortrait";
private static final String REVERSE_LANDSCAPE = "reverseLandscape";
private static final String REVERSE_PORTRAIT = "reversePortrait";
private static final String FULL_SENSOR = "fullSensor";
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("set")) {
String orientation = args.optString(0);
Activity activity = this.cordova.getActivity();
if (orientation.equals(UNSPECIFIED)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
} else if (orientation.equals(LANDSCAPE)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if (orientation.equals(PORTRAIT)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else if (orientation.equals(USER)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
} else if (orientation.equals(BEHIND)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_BEHIND);
} else if (orientation.equals(SENSOR)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
} else if (orientation.equals(NOSENSOR)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
} else if (orientation.equals(SENSOR_LANDSCAPE)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
} else if (orientation.equals(SENSOR_PORTRAIT)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
} else if (orientation.equals(REVERSE_LANDSCAPE)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
} else if (orientation.equals(REVERSE_PORTRAIT)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
} else if (orientation.equals(FULL_SENSOR)) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
callbackContext.success();
return true;
} else {
return false;
}
}
}
pg-plugin-screen-orientation.js
Replace with this:
cordova.define("cordova/plugin/screenorientation", function(require, exports, module) {
var exec = require('cordova/exec');
var ScreenOrientation = function() {};
ScreenOrientation.prototype.set = function(str, successCallback, errorCallback) {
exec(successCallback,
errorCallback,
'ScreenOrientation',
'set',
[str]);
};
var screenorientation = new ScreenOrientation();
module.exports = screenorientation;
});
Then you can replace sample.html with this:
<!DOCTYPE html>
<html>
<head>
<title>ScreenOrientation PhoneGap Plugin Sample</title>
<meta charset="utf-8">
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="pg-plugin-screen-orientation.js"></script>
<script type="text/javascript">
function setOrientation(type){
cordova.require('cordova/plugin/screenorientation').set(
type,
function() {
console.log("Successfully set "+type);
},
function() {
console.error("Failed to set "+type);
}
);
}
</script>
</head>
<body>
<h1>ScreenOrientation PhoneGap Plugin Sample</h1>
<input type="button" onclick="setOrientation('landscape');" value="Landscape" />
<input type="button" onclick="setOrientation('portrait');" value="Portrait" />
<input type="button" onclick="setOrientation('sensorLandscape');" value="Sensor Landscape" />
<input type="button" onclick="setOrientation('sensorPortrait');" value="Sensor Portrait" />
<input type="button" onclick="setOrientation('reverseLandscape');" value="Reverse Landscape" />
<input type="button" onclick="setOrientation('reversePortrait');" value="Reverse Portrait" />
<input type="button" onclick="setOrientation('fullSensor');" value="Full Sensor" />
</body>
</html>
I've put this together as an Eclipse project - you can download it and the resulting APK here
Note: You might want downgrade from Cordova 2.8.0 to Cordova 2.4.0 until issues with pausing the app in Cordova 2.5.0+ have been resolved - see here

Reusing wicket component in a form

I have built a wicket component that contains input/labels and methods to change presentation (required, enabled, etc.). The components render fine, but what happens is when the form submits I see only 1 form parameter 'input', and it's the last InputRow component.
InputRow.html
<html xmlns:wicket="http://wicket.apache.org">
<head>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<wicket:panel>
<label wicket:id="label">abc: <span class="req">*</span></label>
<span class="input">
<input wicket:id="input" type="text" id="name"></input>
</span>
<span wicket:id="input_feedback"></span>
</wicket:panel>
</body>
</html>
InputRow.java
package com.wicket;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.feedback.FeedbackMessage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
public class InputRow extends Panel{
#SuppressWarnings("unused")
private String id;
public InputRow(String id, String label) {
super(id);
this.id = id;
Label memberIdLabel = new Label("label",label);
memberIdLabel.setEscapeModelStrings(false)
.add(new AttributeAppender("for", new Model<String>(id),""));
add(memberIdLabel);
TextField<String> name = new TextField<String>("input");
name.setType(String.class)
.setMarkupId(id)
.setOutputMarkupId(true);
add(name);
add(new Label("input_feedback",""));
}
public InputRow disable()
{
get("input")
.setEnabled(false)
.add(new AttributeAppender("class", new Model<String>("disabled"),""));
get("label")
.add(new AttributeAppender("class", new Model<String>("disabled"),""));
return this;
}
public InputRow required()
{
Model model = (Model)get("label").getInnermostModel();
StringBuffer label = new StringBuffer((String)model.getObject());
label.append(" <span class=\"req\">*</span>");
model.setObject(label);
((TextField)get("input")).setRequired(true);
return this;
}
#Override
protected void onBeforeRender() {
super.onBeforeRender();
Label feedback = (Label)get("input_feedback");
if (get("input").getFeedbackMessage() != null)
{
feedback.setDefaultModel(new Model<String>("Required"));
}
}
}
Adding to the form component
add(new InputRow("name","Name:").required());
edit
I didn't set up a ListView or repeater since I know what rows / fields I want to add to the form at build time.
Your InputFields are missing their models. This way, wicket doesn't know where to store the formdata. If you add models to the fields they will be populated automatically.
There's not just one form parameter submitted. The submits are of the named like name:input, name2:input, ...
But as Nicktar suggests in the comment you should use a model to bind the value of the form component to your entity object. You have to accept an IModel in the constructor and use it in the constructor of TextField.
A better approach to what you are trying to do is to write a Behavior which adds decorating markup for your FormComponent. That way it works for more than just simple text input fields and you can fully customize the instances of your FormComponents.
It could look like this:
public class FormComponentBehavior extends Behavior {
#Override
public void bind(Component component) {
if (!(component instanceof FormComponent)) {
throw new IllegalArgumentException();
}
}
#Override
public void beforeRender(Component component) {
FormComponent<?> fc = (FormComponent<?>) component;
Response r = component.getResponse();
r.write("<label" + (fc.isRequired() ? " class='required'" : "") + ">");
r.write(fc.getLabel().getObject());
r.write("</label>");
r.write("<span class='input'>");
}
#Override
public void afterRender(Component component) {
component.getResponse().write("</span>");
// if feedback errors write them to markup...
}
}
Then you have to add this behavior to your FormComponent instances.
Maybe the problem with your form is that your input text fields have all the same id. Try using attribute 'name' instead of 'id'