How to pretty print result of wicket validator - java

I would like to include reformatting the field content in wicket field validation.
Example time input field:
User input: 1459 -> Validation is ok -> field displays reformatted value: 14:59 (with colon in the middle)
Thanks for any help,
uli
public class PhoneValidatorWrapper implements IValidator<String>, Serializable
{
public PhoneValidatorWrapper()
{
}
#Override
public void validate(IValidatable<String> validatable)
{
// validation goes here ...
// writing pretty print back to model
validatable.getModel().setObject("hello world");
}
}
but still value displayed remains unchanged

I would suggest to use javascript that reformats the user input on the client side. The following jQuery plugin could probably do the job:
http://digitalbush.com/projects/masked-input-plugin/#demo
Also see:
How to have users enter a formatted date in wicket?

I finally found out how to do it:
it works by combining validator and behavior:
public class PhoneValidatorWrapper extends Behavior implements IValidator<String>, Serializable
{
String prettyFormattedValue = null;
public PhoneValidatorWrapper()
{
}
#Override
public void validate(IValidatable<String> validatable)
{
// validation goes here ...
prettyFormattedValue = internalValidationResult.getPrettyValue();
}
#Override
public void beforeRender(Component component)
{
super.beforeRender(component);
IModel defaultModel = component.getDefaultModel();
defaultModel.setObject(prettyFormattedValue);
}
}

Related

Struts2 file upload - execute() is not being invoked

I'm using Struts2 2.5.20 and have written a file upload action that almost works. I can see in the debugger that setReport(), setReportContentType() and setReportFileName() are being called and the parameter values are correct. However, the execute() method is never invoked. I tried following the call stack to see where it should have been called, but there's just layer after layer of interceptors that I can't find the bottom.
Does anyone know what the reason for execute() might be?
public class ImportReportAction extends CampaignerActionSupport implements ValidationAware
{
private File report;
private String reportContentType;
private String reportFileName;
#Override
public String execute() throws Exception
{
...
return SUCCESS;
}
public void setReport(
File report)
{
this.report = report;
}
public void setReportContentType(
String reportContentType)
{
this.reportContentType = reportContentType;
}
#RequiredFieldValidator(type = ValidatorType.FIELD, key = "errors.required", messageParams = { "getText('labels.report.file')" })
public void setReportFileName(
String reportFileName)
{
this.reportFileName = reportFileName;
}
}
Update: I've discovered that the problem is in having the RequiredFieldValidator annotation. When that is present, the validation always fails but the s:actionerror tag is not displaying any message. When the annotation is not present, it allows a user to not pick a file and still calls execute().
The new question is: how to I correctly annotate my class for validation of a file upload?
I had to remove the #RequiredFieldValidator annotation, make my action implement ValidationAware and then implement a validate() method and manually put the validations in there.

Transforming Form Field to Object on Submit

I'm rather new to Play Framework so I hope this is intelligible.
How can I tell play to map a form element to an Object field in the Form's class?
I have a form with a select dropdown of names of objects from my ORM. The values of the dropdown items are the ID field of the ORM objects.
The form object on the Java side has a field with the type of the ORM object, and a setter taking a string and translating it to the object, but on form submission I only get a form error "Invalid Value" indicating the translation is not taking place at all.
My template has a form component:
#helper.select(
createAccountForm("industry"),
helper.options(industries)
)
Where industries is defined in the template constructor by : industries: Map[String, String]
and consists of ID strings to User-Readable names.
My controller defines the class:
public static class CreateAccountForm {
public String name;
public Industry industry;
public void setIndustry(String industryId) {
this.industry = Industry.getIndustry(Integer.parseInt(industryId));
}
}
EDIT: I was doing the setter in the class because this answer indicated to do so, but that didn't work.
EDIT2:
Turns out the setter method was totally not the way to go for this. After banging my head a bit on trying to get an annotation working, I noticed the Formatters.SimpleFormatter and tried that out. It worked, though I don't understand why the extra block around it is necessary.
Global.java:
public class Global extends GlobalSettings {
// Yes, this block is necessary; no, I don't know why.
{
Formatters.register(Industry.class, new Formatters.SimpleFormatter<Industry>() {
#Override
public Industry parse(String industryId, Locale locale) throws ParseException {
return Industry.getIndustry(Integer.parseInt(industryId));
}
#Override
public String print(Industry industry, Locale locale) {
return industry.name;
}
});
}
}
Play is binding the form to an object for you when you use it like described in the documentation: https://github.com/playframework/Play20/wiki/JavaForms
So your controller should look like:
Form<models.Task> taskForm = form(models.Task.class).bindFromRequest();
if (taskForm.hasErrors()) {
return badRequest(views.html.tasks.create.render(taskForm));
}
Task task = taskForm.get();
The task object can have a Priority options list. And you use it in the form (view) like:
#select(editForm("priority.id"), options(Task.priorities), 'class -> "input-xlarge", '_label -> Messages("priority"), '_default -> Messages("make.choice"), 'showConstraints -> false, '_help -> "")
Notice that I am using priorities.id to tell play that a chosen value should be binded by a priority ID. And of course getting the priorities of the Tasks:
public static Map<String, String> priorities() {
LinkedHashMap<String, String> prioritiesList = new LinkedHashMap<String, String>();
List<Priority> priorities = Priority.getPrioritiesForTask("task");
for (Priority orderPrio : priorities) {
prioritiesList.put(orderPrio.getId().toString(), orderPrio.getDescription());
}
return prioritiesList;
}

How do I check for null values in a Wicket Textfield?

I have a Wicket Textfield which contains an Integer value
currentValueTextField = new TextField<IntParameter>("valueText", new PropertyModel<IntParameter>(model, "value"));
I'm attaching a custom validator to this, as follows
currentValueTextField.add(new IntegerValidator());
The validator class is
class IntegerValidator extends AbstractValidator<IntParameter> {
private static final long serialVersionUID = 5899174401360212883L;
public IntegerValidator() {
}
#Override
public void onValidate(IValidatable<IntParameter> validatable) {
ValidationError error = new ValidationError();
if (model.getValue() == null) {
AttributeAppender redOutline = new AttributeAppender("style", new Model<String>("border-style:solid; border-color:#f86b5c; border-width: 3px"), ";");
currentValueTextField.add(redOutline);
currentValueTextField.getParent().getParent().add(redOutline);
validatable.error(error);
}
}
}
However if I type nothing in the textfield, my onValidate() method is not being called.
What is the recommended way to check for null values in this case?
I would also like to do range checking on the value entered.
just call
currentValueTextField.setRequired(true);
to mark the field as required and have Wicket handle null values on it's own. You can easily combine multiple validators per input field.
Any special error handling, like adding red borders or displaying of error messages can be implemented in the onError method of the form or by adding FeedbackBorders to the appropriate fields.
Override validateOnNullValue() that is false by default.
#Override
public boolean validateOnNullValue()
{
return true;
}
This is the description of validateOnNullValue() method:
Indicates whether or not to validate the value if it is null. It is usually desirable to skip validation if the value is null, unless we want to make sure
the value is in fact null (a rare use case). Validators that extend this and
wish to ensure the value is null should override this method and return
true.
currentValueTextField.setRequired(true);
Now you need to customise the error message. So subclass FeedbackPanel.
you can find more information in the following link
Add this class to your form or component
A better (and reusable) way to do this is to override the isEnabled(Component) method of the behavior:
public class HomePage extends WebPage {
private Integer value;
public HomePage() {
add(new FeedbackPanel("feedback"));
add(new Form("form", new CompoundPropertyModel(this))
.add(new TextField("value")
.setRequired(true)
.add(new ErrorDecorationBehavior()))
.add(new Button("submit") {
#Override
public void onSubmit() {
info(value.toString());
}
}));
}
}
class ErrorDecorationBehavior extends AttributeAppender {
public ErrorDecorationBehavior() {
super("style", true, Model.of("border-style:solid; border-color:#f86b5c; border-width: 3px"), ",");
}
#Override
public boolean isEnabled(Component component) {
return super.isEnabled(component) && component.hasErrorMessage();
}
}

How to bind complex types in play-framework 2.0

I have a model class in the following structure:
public class User {
public String name;
public Long id;
}
public class Play {
public String name;
public User user;
}
Now i want to have a form based on Play class. So I have an editPlay view which takes Form[Play] as an input.
In the view I have a form which calls an update action on submit:
#form (routes.PlayController.update())
{..}
but I cannot find the right way to bind the user field in a way I'll receive it properly in the controller:
Form<Play> formPlay = form(Play.class).bindFromRequest();
Play playObj = formPlay.get();
According to the API, Form.Field value is always a string. Is there some other way to automatic bind an input to the User Object?
Thanks
You can make use of custom DataBinder
In the play.scla.html:
#form (routes.PlayController.update())
{
<input type="hidden" name="user" id="user" value="#play.user.id"/>
}
in your method in the controller
public static Result update()
{
// add a formatter which takes you field and convert it to the proper object
// this will be called automatically when you call bindFromRequest()
Formatters.register(User.class, new Formatters.SimpleFormatter<User>(){
#Override
public User parse(String input, Locale arg1) throws ParseException {
// here I extract It from the DB
User user = User.find.byId(new Long(input));
return user;
}
#Override
public String print(User user, Locale arg1) {
return user.id.toString();
}
});
Form<Play> formPlay = form(Play.class).bindFromRequest();
Play playObj = formPlay.get();
}
I'm not quite sure I understand your question, but basically I have been handling forms like this:
final static Form<Play> playForm = form(Play.class);
...
public static Result editPlay(){
Form<Play> newPlayForm = form(User.class).bindFromRequest();
Play newPlay = newPlayForm.get();
....
}
I serve and render the template from an action using:
return ok(play_form_template.render(playForm));
Then in the template:
#(playForm: Form[Play])
#import helper._
#helper.form(action = routes.Application.editPlay()) {
#helper.inputText(playForm("name"))
...
}

#ManagedProperty in backing bean - setting getters and setters

According this article, I've implemented #ManagedProperty(value="#{settings}") to my backing bean:
BEAN Bde.java:
#Entity
#Table(name="bdeDATA")
#ViewScoped
#ManagedBean(name="BDE")
public class Bde implements Serializable
{
/**/
private static final long serialVersionUID = -705775502999920673L;
#Transient
#ManagedProperty(value = "#{settings}")
private Settings settings;
#Id
private Date create_date;
private Integer person_ID;
public Date getCreate_date() {
return create_date;
}
public void setCreate_date(Date create_date) {
this.create_date = create_date;
}
public Integer getPerson_ID() {
return person_ID;
}
public void setPerson_ID(Integer person_ID) {
this.person_ID = person_ID;
try
{
Settings.PWKITEM = (Pwk)Tools.find(person_ID);
if (Settings.PWKITEM != null) settings.setUserfound(true); /// PROBLEMATIC
}
catch (Exception e)
{
Tools.setErrorMessage("NOT FOUND "+e.getMessage());
}
}
// ManagedProperty settings ---------------------------------------------
public Settings getSettings() {
return settings;
}
public void setSettings(Settings settings) {
this.settings = settings;
}
public void setUserfound (boolean userfound){
settings.setUserfound(userfound);
}
public boolean isUserfound() {
return settings.isUserfound();
}
}
Settings.java:
#SessionScoped
#ManagedBean(name="settings")
public class Settings implements Serializable
{
/**/
private static final long serialVersionUID = 8613411699115714416L;
public static Pwk PWKITEM = new Pwk();
private boolean userfound = false;
public boolean isUserfound() {
return userfound;
}
public void setUserfound(boolean userfound) {
this.userfound = userfound;
}
}
XHTML (ajax call setPerson_ID):
<h:inputText id="persId" value="#{bean.bdeitem.persId}">
<f:ajax event="blur" render="name" execute="#this" />
</h:inputText>
<h:inputText id="name" value="#{bean.pwkitem.name}"/>
Problem is in try/catch:
without the condition, object is found.
when I change the condition for example to if (Settings.PWKITEM != null) System.out.println("HELLO"), HELLO is writen to console.
if i try to add the userfound setter, it is catched ("NOT FOUND").
What I'm doing wrong?
Your question looks seriously confusing. You first show some bean code and then immediately say "I though that is an ajax problem,", before even mentioning any kind of problem. The rest of the question is not much different.
To directly answer the last part of your question though:
Ican't understand, why it find the item an writes the correct name to console, and immediatelly after that, it writes catch exception not found....????
You are accessing Settings statically. The instance you have declared at the class level seems to be useless. It's fully possible that if Tools.find throws an exception and thus no new value is assigned, that there is still an old value in the static Settings.PWKITEM field. There is nothing strange about that.
Do note that the log reads from top to bottom. So it's not that "***" is printed and then the exception is thrown, but the exception is first thrown and "Not Found" is printed, and only thereafter "***" is printed.
Additionally, your approach to all of this looks problematic. Declaring an Entity to also be a (JSF) backing bean is rarely a good idea. Using references to some kind of Service or DAO classes from within an entity is also not always a good idea, but doing this in a method that is supposedly a simple setter for an ID simply looks wrong.
Then using static references is even more wrong and to top if off, using underscores in method and non-static variable names goes against the common Java code convention.

Categories