Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to return a feedback error, but still allow wicket to update the component models?

Tags:

java

wicket

I have a wicket form which contains many TextField input components. There's a Validator attached to most of these inputs.

Suppose I've entered 50 values, and one of those fails a range validator. Wicket then generates an error feedback message, but also does not update the models associated with each component. Result is that I lose all 50 values I just entered, and have to type them in again.

My question is, can I tell Wicket to update the models of those components which had valid values, but just report an error for the bad value?

Digging around in the framwork, I noticed this code fragment in FormComponent, which seems to be indicating that if there is an error, then don't update the model.

public final void processInput()
{
    inputChanged();
    validate();
    if (hasErrorMessage())
    {
        invalid();
    }
    else
    {
        valid();
        updateModel();
    }
}

Is there any way to customise this behaviour, and achieve my aim of retaining all valid values?

like image 553
Andrew Fielden Avatar asked Nov 02 '11 11:11

Andrew Fielden


1 Answers

I'd bet that FormComponent.processInput() is not being called at all here. When you submit the Form, Form.process() gets called. There, it will call Form.validate(), which in turn will call Form.validateComponents(), ultimately using FormComponent.validate().

The problem you're having here is the global handling in Form.process(). The form submits fully, or not at all. When a FormComponent.validate() fails, Form.hasError() will return true, and therefore Form.process() will never update any of the models.

You could:

  • Move all FormComponent independent validations to a FormValidator. There you can choose to update the Models of those FormComponents that pass their validations.
  • Implement Form.onError() and use a visitor there to update the models of valid FormComponents.
  • Override Form.process() and modify the // If a validation error occurred branch to use your own methods to mark components as valid/invalid, and update (or not) model objects, depending on the FormComponent having errors. FormComponent.hasErrorMessage() will tell you if validation failed on a certain FormComponent.

UPDATE

After discussing the reasons why user input was lost with the OP, it turned out that the FormComponents were being added in a ListView that did not have setReuseItems set to true. This was causing FormComponents to be created anew on each ListView.populateItem(), therefore losing all user input.

More information on the nature of this problem can be found here:

There are however a few provisions you have to take care of when using a repeater in the form. Usually repeaters clear out their items at the beginning of every request, when inside a form this is usually undesirable because you want to preserve the old items because you want them to keep their state as opposed to being recreated fresh.

For example, if you use ListView, you should call ListView.setReuseItems(true) inside the form so that it preserves old items instead of always creating new ones everytime.

like image 130
Xavi López Avatar answered Nov 04 '22 11:11

Xavi López