I have an IFormValidator that checks if the values of multiple FormComponents are coherent.
Now if validation fails, I'd like to highlight all related FormComponents and respective HTML label tags, just like it happens with Validators, that are responsible for only a single FormComponent (e.g. StringValidator).
My first try was calling FormComponent#invalid() on all related FormComponents, but that doesn't seem to do the trick, since it just calls FormComponent#onInvalid(), which does nothing by default.
The second thing I tried was calling FormComponent#error(String) on each component but that of course generates an additional error message for each FormComponent, which is not the desired behaviour. But at least it does highlight the individual invalid FormComponents.
What would be the correct way to do this? Is there a simple way I'm overlooking, since the IFormValidator#getDependentFormComponents() method, which I'm supposed to implement, already tells the Validator, which FormComponents will be invalid as a result failing the validation?
Here is a stripped down example of what I tried with Wicket 8.3:
wicketForm.add(new IFormValidator() {
#Override
public FormComponent<?>[] getDependentFormComponents() {
return new FormComponent<?>[] {formComponent1, formComponent2, formComponent3};
}
#Override
public void validate(Form<?> form) {
if (/*values of formComponent1-3 are not coherent*/) {
form.error("<error message>");
/* No highlighting at all */
formComponent1.invalid();
formComponent2.invalid();
formComponent3.invalid();
/* Highlighting works, but obviously produces same error message multiple times */
formComponent1.error("<error message>");
formComponent2.error("<error message>");
formComponent3.error("<error message>");
}
}
}
);
A FormComponent is deemed as invalid only when its #error() methods are called - see org.apache.wicket.markup.html.form.FormComponent#isValid().
If you want to show only the error feedback message of the Form then you need to instantiate your FeedbackPanel as:
new FencedFeedbackPanel("id", new ComponentFeedbackMessageFilter(form));
This way it will render the feedback messages only of the Form.
You can use the feedback messages of the form components to show their specific errors next to the respective HTML form element (input, select, etc.)
Related
Okay, this is very strange.
All I am having is a Hyperlink in my menu:
Hyperlink eventCalendar= new Hyperlink("Eventkalender", "eventCalendar=" + store.getId());
and I am listening to the ValueChangeEvent in the MainViewPresenter. Please notice that I am not doing anything. Right before the creation of the listener I am setting a SimplePanel to be the display for the ActivityManager:
App.activityManager.setDisplay(this.mainView.getMainContentContainer());
History.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
String historyToken = event.getValue();
GWT.log("onValueChange() historyToken " + historyToken);
}
});
But if I click the link what happens is this:
First, for the blink of an eye I can see the browser URL change to
http://localhost:8080/#eventCalendar=1
but it changes immediately back to
http://localhost:8080/#
which causes my landing page to get loaded inside the SimplePanel which I declared as display (see above).
Does anybody have an idea what could cause this behavior because this does not make sense to me? Why does the URL get changed again? Am I using History or Hyperlink wrong?
Most probably your PlaceHistoryMapper returns null for the eventCalendar=1 token, so it's replaced with the default place you gave to the PlaceHistoryHandler. If you're using GWT.create() based on PlaceTokenizers, with a factory and/or #WithTokenizers, that means either you don't have a PlaceTokenizer for the empty-string prefix (#Prefix("")), or that one tokenizer returns null.
That being said, you probably should rather try to use places directly rather than going through the history. That means using a ClickHandler on some widget and calling PlaceController#goTo with the appropriate place. Ideally, that widget would be an Anchor whose href is computed from the result of getToken from your PlaceHistoryMapper with the given place (how the href actually looks depends on your Historian; if you stick to the default behavior, then just prepend a # to the returned token).
Wicket 6 no longer keeps feedback messages in session. Now they are attached to components, which I think is great move but I approach an issue connected with that. I used to remove all feedback messages that were related to the specific form like this :
Session.get().getFeedbackMessages().clear(new ContainerFeedbackMessageFilter(panelForm));
Unfortunetly right now I can't clear it like this:
panelForm.getFeedbackMessages().clear();
For obvious reasons - they are attached to components inside form.
So is there a way to get those feedback messages by only accesing (in my case) panelForm or my only way to go is to call getFeedbackMessages() on all of my components (panelForm.component1, panelForm.component2 etc)?
use FeedbackCollector as in example:
new FeedbackMessagesModel(this) {
#Override
protected List<FeedbackMessage> collectMessages(Component panel, IFeedbackMessageFilter filter) {
return new FeedbackCollector(YourComponent.this.getParent()) {
#Override
protected boolean shouldRecurseInto(Component component) {
return true; // your citeria here
}
}.setIncludeSession(false).collect(filter);
}
};
Yes. You should use FeedbackCollector. Collect the messages and mark them as rendered.
I'm looking for a way to validate a single field at a time. This is so, while a user is filling in a form, each time the keypress or blur event occurs for each field, i can validate that field individually and show / hide its error message.
Is that possible? If so, how can I do it? Some google searching hasn't turned up any results which validate a single field, rather than the whole form.
You can use javax.validation.Validator#validateProperty() for that purpose.
I'd recommend that you try using Javascript Regular Expressions to validate user inputs and show/hide error messages.
I provided a code implementation example in the post at this link: Example using Regular Expresssions
Add an event listener to relevant input field in the DOM to provide responsiveness.
var letterField = document.getElementById('letterField'); // DOM element containing user input
letterField.addEventListener('keyup', function() { // key press event listener using anonymous function
if (event.keyCode === 13) { // run this code if the 'enter' key is pressed
if ( ... ) {
...
};
};
};
If you want to add effects, include the following code to transition the error message. Refer to the jQuery API for other effects:
userInputError.delay(800).fadeOut();
i have a form where i have 5 TextFields that are required and 25 that are optional. I set the required TextFields setRequired(true) and get the Feedback messages i want when this fields are empty.
But how do i achieve such an effect that i get warning messages in my feedback panel when the 25 fields are empty but the form still does submit correctly? I want to inform the user that these fields are optional, but it would be nice if he would fill them.
I know i can in onSubmit() add warnings through the warn() procedure. But in on submit i can only check the model for this values, i dont have the component that is empty. But i would like to have the functionality of Validators so that i can say to the user that Field 'optionalTextField1' has no value but it would be nice if you fill it, i can user properties for the messages and so on.
Any ideas how to do this?
you can implement your own IValidator pass the componente as variable and use warn, for example
public void validate(IValidatable<String> validatable)
{
String value = validatable.getValue();
if (value.isEmpty())
{
component.warn("some nice message")
}
}
just an example, not tested though
Solved this through overriding checkRequired()
#Override
public boolean checkRequired() {
if (!isRequired() && getValue().isEmpty()) {
warn("Field'" + getLabel().getObject() + "' is empty. We suggest to fill it.");
return Boolean.TRUE;
}
return super.checkRequired();
}
getLabel().getObject() requires that you setLabel(Model.of("Nice field name"));
I have a form (form.jsp) and a connected FormAction ActionA. ActionA does validations and stores ActionErrors and the form.jsp will print them using <html:errors../> tag.
All this is working fine.
I then wanted to add some on-the-fly server side validation on onblur event on one of the form fields (fieldA). I do this using jQuery's $.post. It goes to a different Action class (ActionB) which will return a value, that I can print in a div under fieldA. This also works fine.
The problem is to combine the two. I use saveErrors method in ActionA and need to reset it with the new errors I get in ActionB.
Example: If fieldA was value "A" and fieldB was "#$" and my ActionA returned errors "No capitals for fieldA" and "No symbols for fieldB" on pressing Submit, then when user changes fieldA to "123" and presses tab, the errors shown should be "No numbers for fieldA" and "No symbols for fieldB" i.e. first error gets removed.
But how do I access the errors, if it isn't in the request!
Ok I worked it out. I just used jQuery to make the entire div with the error (class="globalError") not show (display:none) and then added my new errors in a similar div under that.. so, it just looks like the errors section changes :-). Thanks for the help.