User friendly form validation with Wicket

User friendly form validation with Wicket

September 3, 2008 22:12 46 comments

By default Wicket shows error messages together in a single place in the HTML form. This has some drawbacks to usability, especially if you have long forms with lots of fields. Read further for a tutorial exploring possibilities to improve the location of the error on the page, thereby improving usability.

The default FeedbackPanel shows all errors in one place. When you enter a wrong value in an input field below the fold, the input field is a mile away from the error above the form. This makes it unclear which error message corresponds to which field.

form-usability-scanning.png

The image on the left shows that a lot of page scanning is needed even with moderate sized forms.

With more than a few fields, the user is confused as which error corresponds to which field. It is a big problem when your e-commerce site scares away many potential clients who can’t complete your web forms!

The default form

Before I describe how to create a more user friendly form, first the ‘default’ form. The following is an example of a standard Wicket form. This kind of form is the one you get without doing any ‘special’ magic things. Place your mouse cursor over the image to see the default error messages above the form.

Default Wicket form with FeedbackPanel at the top

This form will be the starting point for our improvements.

The improved form

This is what we are going to make:

Better and improved Wicket form with FeedbackLabels throughout

As you can see, the error messages are directly next to the component that caused the error. This reduces the scanning of the page to link the error message to the right form component.

Step 1: Introducing the FeedbackLabel

The FeedbackLabel is a custom component I’ve written for this tutorial. With this custom label, you can show important feedback messages related to a FormComponent.

This has the advantage that you can place your Feedback messages in any place you want.

Add this to the Java part of the form:

// This shows feedback when the name input is not correct.
FeedbackLabel nameFeedbackLabel = new FeedbackLabel("name.feedback", name);
form.add(nameFeedbackLabel);
 
FeedbackLabel colorFeedbackLabel = new FeedbackLabel("color.feedback", color, customText);
form.add(colorFeedbackLabel);

Add another SPAN tag for every feedback label. You can place this near the relevant form component within the form.

Step 2: Removing the FeedbackPanel completely? No, filtering!

At first, it looks like you can remove the FeedbackPanel completely. But, then you will not be able to use the info() method to display text inside the FeedbackPanel! Therefore we need a way to filter the FeedbackMessages so error messages are not shown. I have written a FeedbackMessageFilter to accomplish that. It filters out the unwanted error messages.

// filteredErrorLevels will not be shown in the FeedbackPanel
int[] filteredErrorLevels = new int[]{FeedbackMessage.ERROR};
feedback.setFilter(new ErrorLevelsFeedbackMessageFilter(filteredErrorLevels));

I have included the ErrorLevelsFeedbackMessageFilter in the project files, so you can reuse this in your existing projects. Remember if you use the error() method, you cannot use this filter! Instead, create your own filter that filters based on components.

Step 3: Adding some style, the ComponentVisualErrorBehavior™

I always love extremely long class names, like the BookmarkablePageRequestTargetUrlCodingStrategy or the SharedResourceRequestTargetUrlCodingStrategy. It makes my day to introduce a class name consisting of four words, the ComponentVisualErrorBehavior™.

This behavior changes the CSS styles for components that are invalid according to the Wicket form validation. You see in the screenshot that the textfield has a red line around it. This is the result of the ComponentVisualErrorBehavior. You can easily change the styles that are applied.

form-usability-tutorial-namefield.png

To add the ComponentVisualErrorBehavior to your component, just add one line in your Java code:

name.add(new ComponentVisualErrorBehavior("onblur", nameFeedbackLabel));

“onblur” stands for the event that triggers this Behavior. The nameFeedbackLabel will also be updated when this is triggered, so that it will show the relevant error (or nothing if the input is valid).

Download

Download the complete example project and start experimenting! (run with mvn jetty:run and connect to http://localhost:8080/demo)

Let me know how and where you use it in the comments!

46 Comments

  • Cool! Have you suggested getting the FeedbackLabel stuff into Wicket proper, or at least Wicket Extensions?
    I can definitely see it having a place there, I know Al Maw (who is one of the committers) held a presentation on this sort of thing during a London Wicket User Group meetup, although that was good, I really like your approach to it.

    I’d love to use this in Wicket RAD for error messages.

  • Daan

    Thanks for the compliment!
    My goal was to write unobtrusive components that do the heavy lifting by themselves.
    If you find it useful, feel free to include it in Wicket RAD or any other project.

  • Since I am not aware of anything like this in core Wicket, if you are fine with it, I’ll put it into Wicket RAD (Apache License) and just repackage the components a little.

    Looked at the code (haven’t tried it yet though) – very simple, but also very, very useful. The way it should be. :)

  • Daan

    Including is fine by me :-) .

  • Sorry for bugging you all the time – one question came up: how would you deal with Form level validators?
    For instance, “match password” type validation with two password fields?
    I believe these wouldn’t turn up for the individual FormComponents (not sure though).

    I haven’t tried it yet, but maybe adding something like this to the ErrorLevelsFeedbackMessageFilter class might work:
    public boolean accept(FeedbackMessage message){
    if(message.getReporter().equals(parentForm))
    return true;

  • I’m quite tired right know, so please excuse me, when I am talking total bullshit now ;) However, have you thought about using a Border instead of FeedbackLabel? To make my idea clearer, here is what the HTML would look like:

    Form:
    [div wicket:id="feedbackBorder"]
    [label ...]Name:[/label]
    [input ... /]
    [/div]

    Border:

    [wicket:border]
    [span wicket:id="msg"][/span]
    [wicket:body /]
    [/wicket:border]

    produced HTML, no error: same as template
    produced HTML, error:
    [div wicket:id="feedbackBorder" class="error"]
    [span]this is an error message[/span]
    [label ...]Name:[/label]
    [input ... /]
    [/div]

    that way, you wouldn’t need an extra behaviour to style the erroneous input field. one could even give a light red background to the surrounding div (just an example).

    regards, stefan

  • Daan

    It didn’t come up with me to use a Border. But I guess Border has it’s own markup? That makes it a bit heavy-weight, because you need to create separate Border components (+markup) for each Form Component.
    I believe the FeedbackLabel is less intrusive, because you can just insert it in existing Forms without changing the hierarchy. The Form component itself is not aware of the FeedbackLabel, which is a Good Thing.

  • Yes, Border has its own markup. But no, you wouldn’t need to create a separate Border for each FormComponent. And yes, you would have to change the hierarchy:

    old:
    add(new SimpleFormComponentLabel(…));
    add(new TextField(…));

    new:
    add(border = new FeedbackBorder(…));
    border.getBodyComponent(..).add(new SimpleFormComponentLabel(…));
    border.getBodyComponent(..).add(new TextField(…));

    Most people wouldn’t have to change their markup though, as most forms consist of either table rows or divs anyway. Hence:

    old:
    [div][label wicket:id=""][/label][input wicket:id=""/][/div]
    new:
    [div wicket:id="'][label wicket:id=""][/label][input wicket:id=""/][/div]

    You should definitely have a look at Borders. They really simplify/beautify a lot of things. However, it takes some time to fully understand the concept and it’s powers – it took me at least ;)

    I’ll go and implement that border myself as I’m in the lucky situation to start a new project from scratch today – lucky me ;) – where I have the ability to play around with that kind of stuff. If I succeed, I’ll post it on my blog (http://talk-on-tech.blogspot.com). So you better keep an eye on it ;D

    best regards

  • Daan

    I’m curious to see your Border solution.

  • Ricardo Mayerhofer

    I had trouble using the feedback label with CompoundPropertyModel in forms.
    The error was: WicketMessage: No get method defined for class.

    To fix just replace:

    this.setModel( nulll );
    by
    this.setModel( new Model( “” ) );

    on the method onBeforeRender in FeedbackLabel.

  • Steve

    Great work BUT I also had a problem with using it with CompoundPropertyModel in my form. The solution above didn’t fix it. It kept requiring a getter for the field in my model backing the form. In the end, I just added one to my model and ignore it.
    Can you think of a more elegant solution?

  • Steve

    I made a modification so that you can attach the Feedbaklabel to Form’s themselves, rather than just FormComponents. This is so you can collect messages that original from the Form as well as FormComponents. Messages like ‘Upload too large’ or ‘upload failed’ originate from the Form.

    The simple fix is to change FormComponent in Feedbacklabel.java to be Component, not FormComponent. I’ve pasted the full modification below:

    /*
    * Copyright 2008 Daan, StuQ.nl
    * Licensed 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 nl.stuq;

    import org.apache.wicket.AttributeModifier;
    import org.apache.wicket.Component;
    import org.apache.wicket.markup.html.basic.Label;
    import org.apache.wicket.markup.html.form.Form;
    import org.apache.wicket.markup.html.form.FormComponent;
    import org.apache.wicket.model.IModel;
    import org.apache.wicket.model.Model;

    /**
    * Label displaying feedback messages for FormComponents.
    *

    * You can use this Label to show the error message near the actual FormComponent, instead of in the FeedbackPanel
    * It’s safe to remove the FeedbackPanel if you use this class for every FormComponent in your Form.
    *

    * You can use this code under Apache 2.0 license, as long as you retain the copyright messages.
    *
    * Tested with Wicket 1.3.4
    * @author Daan, StuQ.nl
    * @author Steve Swinsburg, s.swinsburg@lancaster.ac.uk
    */
    public class FeedbackLabel extends Label {

    /** Field component holds a reference to the {@link Component} this FeedbackLabel belongs to
    * Generally this is a FormComponent like a TextField, but can also be the Form itself.
    * Using the form itself is useful for collecting errors that come from the Form and not from a FormComponent,
    * like upload too large etc. */
    private Component component = null;

    /** Field text holds a model of the text to be shown in the FeedbackLabel */
    private IModel text = null;

    /**
    * Call this constructor if you just want to display the FeedbackMessage of the component
    * @param id The non-null id of this component
    * @param component The {@link FormComponent} to show the FeedbackMessage for.
    */
    public FeedbackLabel(String id, Component component) {
    super(id);
    this.component = component;
    }

    /**
    * Call this constructor if you want to display a custom text
    * @param id The non-null id of this component
    * @param component The {@link FormComponent} to show the custom text for.
    * @param text The custom text to show when the FormComponent has a FeedbackMessage
    */
    public FeedbackLabel(String id, Component component, String text) {
    this(id, component, new Model(text));
    }

    /**
    * Call this constructor if you want to display a custom model (for easy i18n)
    * @param id The non-null id of this component
    * @param component The {@link FormComponent} to show the custom model for.
    * @param iModel The custom model to show when the {@link FormComponent} has a FeedbackMessage
    */
    public FeedbackLabel(String id, Component component, IModel iModel) {
    super(id);
    this.component = component;
    this.text=iModel;
    }

    /**
    * Set the content of this FeedbackLabel, depending on if the component has a FeedbackMessage.
    *
    * The HTML class attribute will be filled with the error level of the feedback message. That way, you can easily
    * style different messages differently. Examples:
    *
    * class = “feedbacklabel INFO”
    * class = “feedbacklabel ERROR”
    * class = “feedbacklabel DEBUG”
    * class = “feedbacklabel FATAL”
    *
    *
    * @see Component
    */
    @Override
    protected void onBeforeRender() {
    super.onBeforeRender();
    setModel(null);

    if(component.getFeedbackMessage()!=null){
    if(this.text!=null){
    this.setModel(text);
    } else {
    this.setModel(new Model(component.getFeedbackMessage().getMessage()));
    }

    this.add(new AttributeModifier(“class”, true, new Model(“feedbackLabel ” + component.getFeedbackMessage().getLevelAsString())));
    } else {
    this.setModel(null);
    }

    }
    }

    I would still like to know how to get it to work when using a CompoundPropertyModel backing a form. The current workaround (working for me) is to have a getter in the POJO for the property although I’d prefer not to do this.

    cheers.

  • Daan

    Form level validators cannot be linked to one FormComponent, so they wouldn’t show up in the FeedbackLabel. You need to change the ErrorLevelsFeedbackMessageFilter for them to show up, as you already said.

    About your example, “match password” type validation with two password fields. Isn’t it possible to link the validator to the second password field and when the second password field does not match the first, you get an error next to the second field.
    The first password field gets a ‘Required’ validator. That way, the first password field is required to be non-empty and the second password field is required to exactly match the first.

    By the way, there are other IFeedbackMessageFilter implementations:

  • [...] les PageLink – Wicket : découpler les composants pour les mises à jour Ajax – Wicket : avoir les feedback à côté des saisies (un point sur lequel je voulais blogger un de ces jours… plus besoin et vive le web !) – [...]

  • hi

    the compoundpropertymodel (CPM) issue is normal : when using CPM, each element of the form will be looked for in the CPM. Hence the “not get for FeedbackLabelID”.

    You just have to say explicitly that you don’t want the FeedbackLabel to share the CPM :
    add(new FeedbackLabel(“fbLabel”, name, new Model(null)));
    ==> the new Model(null) does matter ;)

    BTW, for wicket 1.4 and probably even for earlier version, you should also change the onBeforeRender as well like this :

    @Override
    protected void onBeforeRender()
    {
    super.onBeforeRender();

    if(component.getFeedbackMessage()!=null)
    {
    if(this.text!=null){
    setDefaultModel(this.text);
    } else {
    setDefaultModel(new Model(component.getFeedbackMessage().getMessage()));
    }

    this.add(new AttributeModifier(“class”, true, new Model(“feedbackLabel ” + component.getFeedbackMessage().getLevelAsString())));
    } else {
    setDefaultModel(new Model(“”));
    }
    }

  • Me again !

    I’ve found a better way to deal with the fact that some messages have been already rendered.

    In the FeedbackLabel onBeforeRender, just do “component.getFeedbackMessage().markRendered();” after having taken the component message.

    When you declare your FeedbackPanel of the page, just add the following filter :
    FeedbackPanel panel = new FeedbackPanel(“feedbackPanel”);
    panel.setFilter(new IFeedbackMessageFilter(){

    public boolean accept(FeedbackMessage message)
    {
    return !message.isRendered();
    }

    });

    Thus messages already rendered won’t appear in the feedback panel. And consequently we’re now sure that all messages will be shown :)

    ++
    zedros

  • Hi

    me again ! :$

    In fact, when trying your FeedbackLabel, I realised that I was looking for something closer to a feedback panel dedicated to the component. Indeed, if multiple messages are expected, I don’t want to have just one next to the component and the others in the main feedback panel.

    Thinking twice about it, I found a really easy solution, using just FeedbackPanel, I put it here in case it helps.

    In your form, first make final the component concerned :
    final RequiredTextField name = new RequiredTextField(“name”);
    add(name);

    Then, add the feedbackpanel overriding the accept() method to define precisely what you want :
    FeedbackPanel dedicatedFP = new FeedbackPanel(“fbLabel”);
    dedicatedFP.setFilter(new IFeedbackMessageFilter(){

    public boolean accept(FeedbackMessage message)
    {
    if (message.getReporter().equals(name) && !(message.isRendered())){
    message.markRendered();
    return true ;
    }else{
    return false ;
    }

    }});
    add(dedicatedFP);

    I explicitly accept only messages from my component. Furthermore, in my case, I don’t want to have them twice in my page, so I check for “isRendered()” first, then mark it as rendered when dealt with by my feedbackpanel.

    Then, to be sure I miss no message, I put a feedbackpanel for my whole form :
    FeedbackPanel panel = new FeedbackPanel(“feedbackPanel”);
    panel.setFilter(new IFeedbackMessageFilter(){

    public boolean accept(FeedbackMessage message)
    {
    return !message.isRendered();
    }

    });
    add(panel);

    Once again, I check for isRendered.

    Nice and easy isn’t it ?

    For sure, one can easily makes his own DedicatedFeedbackPanel(String id, Component component) if needed, and with exactly what is needed => we could decide to check for one precise level of feedbackmessage or… As well, the mono rendering, or not, is up to the end user.

    I hope it helps !

    Cheers
    zedros

  • [...] Dans ma dernière revue de presse, j’avais parlé d’un blog traitant d’un moyen d’avoir les feedbacks à côté des saisies. [...]

  • Srinivasa Raju CH

    Hi,
    I have used the code to add error message for a field. I am using wicket 1.4 I am getting the error message withe code that you gave. This is the error message….

    WicketMessage: Error attaching this container for rendering: [MarkupContainer [Component id = form]]Root cause:java.lang.IllegalStateException: Attempt to set model object on null model of component: form:name_feedback

    Still more error stack. Can you please tell me why I am getting this error.

  • Hi Srinivasa,

    I have no idea why it does not work with Wicket 1.4. We’re currently running on 1.3.5 and it should work on that.
    If you (or someone else) finds a solution, please share it!

    - Daan

  • Srinivasa Raju CH

    Hi Daan,
    I have testing your demo application with jetty. The component visual behavior is working fine with text fields, but the same is not working for radio button, I mean on selection of the radio button the error message beside the field is still showing. I even tried by changing the event (onblur) to onchange even it is not working for radio buttons. Can you please check once and let me know why so….

    – Srinivas.

  • Hi Srinivasa Raju CH,

    The radio buttons do not have the ComponentVisualErrorBehavior attached in the demo. I think it wouldn’t work in the same way for radio buttons as for form fields.

    It’s currently not very easy to trigger Ajax behaviors for radio buttons. See this post on the mailing list for a solution.

    – Daan

  • Ashis

    Hello all,
    I have used this approach of validation in wicket.It worked for textfields but did not work on AutoComplete textfield.

    Any suggestions will be gratefully appreciated

    thanks

  • Maarten

    You might find these components from elephas interesting as well:

    http://code.google.com/p/elephas/source/browse/trunk/src/main/java/org/elephas/webapp/frontend/component/common/form/

    According to the commit message, it’s based on Al Maw’s ShinyForm.

  • Hi Maarten,

    These look indeed quite similar :-)
    Thanks for the link!

    - Daan

  • Can anyone think of a way to use taborder instead of onBlur? onBlur does not work for radiobuttons etc. Or maybe a way to add a wicket behavior to focus on the next element when the previous element is validated?

  • We are doing something similar, but instead of having extra code (panels to show the error) for each field we just have a visitor that goes through the form and then adds a border/changes style class etc. to every component that failed validation. We also have a variant that dynamicly inserts the “feedback label” using dom manipulation and ajax, e.g. adding new component markup and the component dynamicly.

  • [...] Form Validation & Default Error Handling: There are validators available to enable basic checking like required, number / pattern / range / date validator. Anything above that needs to be custom built and adds to the verbose nature of the framework. For example a "FormValidator" was built to support the validation for each elements of the form. Custom messages for each validation message can be displayed as explained here. More user-friendly messages can be displayed as explained here. [...]

  • If you want to use this in 1.4 you will need to change the setModel method to setDefaultModelObject as stated in the migration guide to 1.4

  • Timo

    Aargh… This kind of workarounds/extensions/whatever of frameworks just make me more unsure if Java is not a right tool create web applications. IMHO, things like these should be easily available in the framework itself…

  • Antoine

    Maybe I missed something – but why go to the trouble of creating a new component instead of using a feedback filter which is readily available in the Wicket framework?

    Example:
    FormComponent nameField = new RequiredTextField(“name”);
    add(new FeedbackPanel(“nameFieldFeedback”, new ComponentFeedbackMessageFilter(nameField)));

    That feedback panel will only show messages relevant to the nameField component, exactly what your FeedbackLabel component is doing.

  • Björn

    Hi there,
    i tried using this FeedbackLabel with the ComponentVisualErrorBehavior.
    But there is one thing I don’t understand:
    while the field is invalid it shows me the correct Errormessage, but when I go back and correct the input to be valid, the error message doesn’t disappear. How do I make it delete it again? Since the onError(..) method is still called not even the style-class is set to “valid” Why could that be?
    I’d appreciate some help, thanx in advance
    Cheers Björn

  • Mark

    Nice article!!
    I have one question regarding validation with models which are direclty bound to hibernate entities. The problem i have if i use your component that wicket looks for getter/setter of the feedbacklabel which of course doesnt exists. Is there a elegant way to say wicket dont use the feedbacklabel for the model bound to the form? I am new to wicket so my question could be stupid :-) .
    Thanks for your help!

  • Mark

    Sry for my last post – i just red the other comments and this solution works! Thanks!

  • Hi guys,

    in contrast of filtering everything belongs to the errorlevel (e.g. FeedbackMessage.ERROR) I’ve written a simple FeedbackLabelsMessageFilter (see below). This filter can be set to a FeedbackPanel. Afterwards the FeedbackPanel will show all FeedbackMessages except those belong to a specific FeedbackLabel.
    Simply add any FeedbackLabel you want to the filter with the “add(FeedbackLabel)”-Method.

    An extension may be to pass a Form to the filter and extract the FeedbackLabels automatically.

    Code:

    import java.util.HashMap;
    import java.util.Map;

    import org.apache.wicket.feedback.FeedbackMessage;
    import org.apache.wicket.feedback.IFeedbackMessageFilter;
    import org.apache.wicket.markup.html.form.FormComponent;

    /**
    * Filter für FeedbackLabels
    * FeedbackMessages von FeedbackLabels die diesem Filter hinzugefügt sind, werden herausgefiltert
    * @author graetz
    *
    */
    public class FeedbackLabelsMessageFilter implements IFeedbackMessageFilter {
    private static final long serialVersionUID = 5370472114377586647L;

    private Map<FormComponent, FeedbackLabel> mapFeedbackLabels = new HashMap<FormComponent, FeedbackLabel>();

    @Override
    public boolean accept(FeedbackMessage message) {
    if(mapFeedbackLabels.containsKey(message.getReporter())) {
    return false;
    }
    return true;
    }

    /**
    * fügt ein FeedbackLabel diesen Filter hinzu
    * @param feedbackLabel
    */
    public void add(FeedbackLabel feedbackLabel) {
    mapFeedbackLabels.put(feedbackLabel.getFormComponent(), feedbackLabel);
    }
    }

    greets
    ben

  • This is great, but did you… did you actually TRADEMARK the class name? Why on Earth would you do such a thing?

  • Oops….. just ignore that. This is convention of my company :-)

  • Shawn

    Daan,

    I’m seeing a problem when changeCssClass is called it wipes out the onclick and onkeyup handlers I have on that particular field the fieldlabel is associated with.

    I think this line in particular does it:

    ajaxRequestTarget.addComponent(formComponent);

    The handlers are set dynamically and work until the feedback label is shown via changeCssClass().

    in the javascript:

    fields[i].onkeyup = function(){ keyUpHandler(this);};
    fields[i].onclick = function(){ clickHandler(this);};

  • If you add the Javascript via a Wicket behavior, it should be retained even with an Wicket Ajax update.

  • I’m able to get this to work when it’s added a basic panel. But when I want to add it to a list of ajax tabbed panels, the label never appears. The validation works, but no message. I have an unknown number of drivers, so I have to created a dynamic list of driver tabs in the tabbed panel.

    What am I missing?

    Here’s a snippit:

    public final class DriverPanel extends Panel {
    AjaxTabbedPanel driverTabbedPanel = null;
    List tabs = null;
    private List driverList;
    ….

    public DriverPanel(String id) {
    super(id);
    ……
    ……
    driverList = get from db….
    tabs = new ArrayList();
    Iterator drivers = driverList.iterator();
    index = 0;
    while (drivers.hasNext()) {
    DriverBean driver = drivers.next();
    AbstractTab theTab = new AbstractTab(new Model(“Driver ” + index)) {

    final int tabNumber = index;

    public Panel getPanel(String panelId) {
    Panel p = new TabPanel(panelId, new Model(panelId), tabNumber);

    return p;
    }
    };
    index++;
    tabs.add(theTab);
    }
    driverTabbedPanel = new AjaxTabbedPanel(“driverTabs”, tabs);
    add(driverTabbedPanel);
    }

    private class TabPanel extends Panel {

    private FeedbackLabel firstNameFeedbackLabel = null;
    private FeedbackLabel middleNameFeedbackLabel = null;
    private FeedbackLabel lastNameFeedbackLabel = null;
    private int driverNum = 0;

    public int getDriverNum() {
    return driverNum;
    }

    public void setDriverNum(int driverNum) {
    this.driverNum = driverNum;
    }

    public TabPanel(String id, IModel model, int driverNumber) {
    super(id, model);
    driverNum = driverNumber;
    TextField fNameTF = new UpdatingTextField(“firstName”, new PropertyModel(driverList.get(driverNumber), “firstName”), driverNumber);
    TextField mNameTF = new UpdatingTextField(“middleName”, new PropertyModel(driverList.get(driverNumber), “middleName”), driverNumber);
    TextField lNameTF = new UpdatingTextField(“lastName”, new PropertyModel(driverList.get(driverNumber), “lastName”), driverNumber);

    fNameTF.setOutputMarkupId(true);
    mNameTF.setOutputMarkupId(true);
    lNameTF.setOutputMarkupId(true);

    fNameTF.setRequired(true);
    lNameTF.setRequired(true);

    middleNameFeedbackLabel = new FeedbackLabel(“middleName.feedback”, mNameTF);
    firstNameFeedbackLabel = new FeedbackLabel(“firstName.feedback”, fNameTF);
    lastNameFeedbackLabel = new FeedbackLabel(“lastName.feedback”, lNameTF);

    add(fNameTF);
    add(mNameTF);
    add(lNameTF);

    add(middleNameFeedbackLabel);
    add(firstNameFeedbackLabel);
    add(lastNameFeedbackLabel);
    }
    };

    private static class UpdatingTextField extends TextField {

    String fieldName = null;
    int driverNumber = 0;

    public UpdatingTextField(String id, IModel model, int driver) {
    super(id, model);
    fieldName = id;
    driverNumber = driver;
    add(new AjaxFormComponentUpdatingBehavior(“onblur”) {

    @Override
    protected void onUpdate(AjaxRequestTarget target) {
    }
    });
    }
    }
    }

  • Hi gmo,

    I don’t immediately see what’s wrong with your code, or why it shouldn’t work..
    Did you call setOutputMarkupId(true) and setOutputPlaceholderTag(true) on the stuff that has to be refreshed?

    It’s more than 2 years ago I wrote this code, so I don’t know all the nitty-gritty details anymore…

    If you don’t arrive at a solution, you can try the Wicket mailing list…

    - Daan

  • tommy

    Thanks, it’s working, but why i find a bug with password field, when i type password into it, it deleted my input automatic if i jump to next field to continue fill the form..

  • taha özket

    @tommy

    use
    password.setResetPassword(false);

  • rotsch

    hi there!

    are there any solution for the ugly rewrite of the URL?

    I have bookmarkable pages:
    mountBookmarkablePage(“/Login”, Login.class);

    the form validator rewrites this to:
    http://localhost:8080/?wicket:interface=:1::::
    when there is a validation error (e.g. no login-name)

    i haven’t found a solution yet, but i think this case isn’t that uncommon?

    thanks for any reply
    -rotsch

  • If anyone else is still using Daan’s FeedbackLabel, and wondering how to get rid of unnecessary “Component-targetted feedback message was left unrendered.” WARN messages flooding your log, the answer is that component.getFeedbackMessage().markRendered() should be appropriately called in FeedbackLabel’s onBeforeRender().

    More info on Stack Overflow: http://stackoverflow.com/questions/10445703/how-to-avoid-superfluous-wicket-log-warnings-when-using-field-specific-feedbackl

  • [...] I’m using “FeedbackLabels” to show component-specific validation messages, based on ideas and code in this blog post: User friendly form validation with Wicket. [...]

  • Some time ago Daan’s article inspired me to create behavior which does 3 things at the same time:

    – feedback panels refreshing
    – form validity check
    – invalid component marking

    You can check it at http://println.posterous.com/wicket-automatic-ajax-form-validation-marking

  • It’s really a cool and helpful piece of info.
    I’m happy that you simply shared this helpful info with us.

    Please stay us up to date like this. Thanks for sharing.

  • Thanks on your marvelous posting! I seriusly eenjoyed reading it, you happen to be a great author.
    I will be sure to bookmark your blog and will often come back from now on. I
    want to encourage yourself to continue your great posts, have a nice
    day!

Leave a reply