Vaadin 7 Validation (BeanValidator and setrequired) - vaadin

Hi I have just started Vaadin 7 and have got the BeanValidator working. But, I have some issues. The code I am using is the following:
BeanItem<RegisterBean> item = new BeanItem<RegisterBean>(new RegisterBean());
final FieldGroup binder = new FieldGroup(item);
final TextField email = new TextField("email");
email.addValidator(new BeanValidator(RegisterBean.class, "email"));
The validates fine using the BeanValidator. With the #NotNull tag I am able to validate for Null values as well. However, I would like to give the user visual clues that the field in the form can't be left blank. For this, I used:
email.setRequired(true);
However, after adding the setRequired the BeanValidation for the form no longer works?
Is this a limitation?
How do I get around it?

You should probably rely on the bean validation itself and use the fieldgroup.
My model looks as follows:
#NotNull(message="Please enter a valid email address.")
#Email(message="Please enter a valid email address.")
#Size(min = 3, max = 255, message="Please enter a valid email address.")
#Column(name="P_EMAIL", nullable=true, length=255)
private String email;
In your view do either buildAndBind
Field<?> email = binder.buildAndBind("email");
Or use the annotation #PropertyId("email") in your field declaration. The rest is magic.
Instead of FieldGroupuse BeanFieldGroup.
A problem will be that validation is made preliminary. So install the validators on click. More to that topic can be found here: http://morevaadin.com/content/bean-validation-and-vaadin-comprehensive-example/

To complete the example above, using a BeanFieldGroup, as it got validators, you can use the setValidationVisible method of an AbstractField to turn off preliminary validation, then to turn on in a blurListener and in the buttons clickListeners.
AbstractTextField cName = binder.buildAndBind("Name","name", AbstractTextField.class);
cName.setNullRepresentation("");
cName.setValidationVisible(false);
cName.addBlurListener(new MyBlurListener(cName)); //<-- turn on setValidationVisible there
myButton.addClickListener(event -> {
try {
cName.setValidationVisible(true);
binder.commit();
} catch (CommitException e){
Notification.show("Sending error");
}
});

Related

ASP.NET MVC3 Model Error (Previous value in error message)

I'm using ASP.NET MVC 3. I have an integer field and as a test I am entering character values in the text box which are invalid for ints.
So when I test,
I enter an invalid value and click submit.
MVC passes back the following error message:
The value 'FF,' is not valid for FCode.
So then I erase the FF from the form field and enter HH, then click submit. And then MVC gives me the following messages:
The value 'FF, HH' is not valid for FCode.
Then say I change the form field to BB, I get the following error returned:
The value 'HH, BB' is not valid for FCode.
It is always returning the latest 2 in the error message. How can I fix this to only return the latest 1? Users don't want to see their previous mistakes, they only want to see most recent.
Here is the code from my controller:
if (ModelState.IsValid){
//Do valid stuff here
}
else
{
var query =
from val in ModelState.Values
where val.Errors.Count == 1
select val.Errors;
foreach (var error in query.ToList())
{
errorList.Add(error[0].ErrorMessage);
}
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = 500;
return Json(errorList);
}
I was actually binding to same field in the model twice. That is what was causing this. I was using a TextBoxFor and a HiddenFor on the same field.
So when MVC sent the model errors back to my controller on form submit, it was sending 2.
I changed my TextBoxFor to a TextBox and this solved the problem since it is now only bound to the hidden.

Sending Emails with ActionMailer.Mvc in VB, Cannot Find View

The error I get when I try to send an email is:
NoViewsFoundException
You must provide a view for this email. Views should be named
~/Views/Email/VerificationEmail.html.vbhtml.txt.cshtml or
~/Views/Email/VerificationEmail.html.vbhtml.html.cshtml (or aspx for
WebFormsViewEngine) depending on the format you wish to render.
Error on line:
Return Email("~/Views/Email/VerificationEmail.html.vbhtml", model)
Can emails not be sent in .vbhtml, must they be sent in .cshtml? How can this work for VB?
Here is my code controller:
Imports ActionMailer.Net.Mvc
Public Class EmailController
Inherits MailerBase
Public Function VerificationEmail(ByVal model As RegisterModel) As EmailResult
[To].Add(model.Email)
From = "me#my.org"
Subject = "Thanks for registering with us!"
Return Email("~/Views/Email/VerificationEmail.html.vbhtml", model)
End Function
End Class
Here is my view:
#modelType MyBlog.RegisterModel
#Code
Layout = Nothing
End code
Welcome to My Cool Site, #Model.UserName
We need you to verify your email. Click this nifty link to get verified!
#Html.ActionLink("Verify", "Account", New With {.code = Model.Email})
Thanks!
After reading a couple of issues and answer, it could get it to work with this:
public override string ViewPath {
get { return AppDomain.CurrentDomain.BaseDirectory + #"\EmailTemplates\"; }
}
Of course you can have vbhtml email templates you just need to be careful with the naming (the .cshtmls exception message are hardcoded so don't be confused on it)
Your view is named correctly as VerificationEmail.html.vbhtml you just need remove all the prefixes from the view name in the Email call:
Return Email("VerificationEmail", model)
Because ActionMailer will be automatically add the prefixes and select the correct template for you.
Note that currently you cannot use relative viewnames like which start with ~ e.g. "~/Views/..." (I don't know wether this is a bug or feature).
So you need put your mail template to the regular view folders e.g.
/Views/{MailControllerName}/
/View/Shared/
Had the same issue as Chad Richardson. To solve the issue which happens when trying to send email from other area just add this code to Application_Start method:
var razorEngine = ViewEngines.Engines.OfType<RazorViewEngine>().First();
razorEngine.ViewLocationFormats = razorEngine.ViewLocationFormats.Concat(new string[]
{
"~/Areas/.../{0}.cshtml"
}).ToArray();

JSR303 ConstraintValidator, how to show the message without an error page

Im working with JSF 2.0 and Glassfish v3. I was testing the functionality of JSR303 bean validation, so I created a validator which implements ConstraintValidator and then annotate that on a property wich I want to validate.
It works fine, but it displays a Glassfish default error page. I don't want this to be displayed, I would rather have the message displayed in a <h:outputText> or something.
Does anybody know how to achieve this?
Here is my validator method:
#Override
public boolean isValid(String searchArg, ConstraintValidatorContext ctx) {
boolean searchArgCorrect = true;
FacesMessage msg;
if(searchArg!=null) {
ctx.disableDefaultConstraintViolation();
if(searchArg.length() < 3) {
ctx.buildConstraintViolationWithTemplate("Searcharg is too short").addConstraintViolation();
searchArgCorrect=false;
msg = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"Searcharg is too short", null);
throw new ValidatorException(msg);
}
}
return searchArgCorrect;
}
PS: I know that there are easier ways to validate the length of a string, but the above code snippet is only for demo/testing purposes. I have another plans with the validator.
You're mixing two concepts: JSF validation and JSR 303 bean validation. You're implementing JSR303 bean validation, but you're throwing a JSF-specific ValidatorException.
The method should not throw an exception. The method should just return true or false depending on the validation outcome. The message has to be definied in ValidationMessages.properties. JSF will then display it in a <h:message> which is associated with the input component.
See also this documentation on creating custom constraints with a message.
Or if you're actually after a standard JSF validator, then you should be implementing javax.faces.validator.Validator instead, annotate it with #FacesValidator and declare it in view by <f:validator>. It can throw a ValidatorException and the message will be displayed in <h:message> associated with the input component.

In MVC, how can I make a field in a model non-required after a checkbox is checked?

I have a page written using .NET MVC. In the model for a Person called PersonModel I have this defined which requires the user to enter some text in the last name field:
<DisplayName("Last Name"), Required()> _
Public Property LastName() As String
Get
Return _LastName
End Get
Set(ByVal value As String)
_LastName = value
End Set
End Property
On the form, there is a checkbox that a user can check to do some other things. Is there a way, using JQuery preferablly, to change that Last Name field to be non-Required? If not using JQuery I am open to other suggestions but since I am doing alot of things when this check box is checked anyways, I was hoping I could add this logic in there. Here is some sample of what I am doing when this box is checked to demonstrate...
function doOwnerBusiness(event) {
if ($(this).is(':checked')) {
$('input[name="People_1__LastName"], label[for="People[1]_LastName"]').hide();​
$("#People_1__LastName").hide();
$("#People_1__LastName").val("");
$("#People_1__LastName :input").attr('disabled', true);
$('input[name="People[1]_Suffix"], label[for="People[1]_Suffix"]').hide();​
$("#People_1__Suffix").attr('disabled', true);
$('#People_1__Suffix')[0].selectedIndex = 0;
$('#People_1__Suffix').hide();
}
else {
$('input[name="People_1__LastName"], label[for="People[1]_LastName"]').show();
$("#People_1__LastName").show();
$('#People_1__LastName :input').attr('disabled', false);
}
}
Any help with this would be appreciated folks.
Thank you
William
Here is how I am declaring my checkbox and also part of the function where I am trying to check if it is checked or not...
<%=Html.CheckBoxFor(Function(model) model.FirstNameAsBusiness)%>
<%=Html.LabelFor(Function(model) model.FirstNameAsBusiness)%>
Function Nominate(ByVal m As NominationModel, ByVal captchaValid As Boolean) As ActionResult
If Not m.FirstNameAsBusiness.checked AndAlso String.IsNullOrEmpty(m.lastnametext) Then
ModelState.AddModelError("LastName", "Last Name field is required if you don't yada yada...")
Return View()
End If
Short answer: no. You can't bypass the DataAnnotation with a jQuery call.
Technically, the Last Name field isn't required. So, I'd remove the DataAnnotation for Required, and then on the backend, when the user submits the form, verify that a field value exists when the checkbox isn't checked. If the conditional doesn't pass, and an error to ModelState for that field, and redirect to the page. (apologies for the c#):
public ActionResult Index(HomeIndexModel form)
{
if (!form.Checked && string.IsNullOrEmpty(form.LastName))
{
ModelState.AddModelError("LastName", "Last Name field is required if you don't yada yada...");
return View();
}
//conditional requirement passed...
}
If you want to get a little fancier, you can check out this thread, though all of the suggestions here are also server-side:
ASP.NET MVC Conditional validation

asp.net mvc validation must be a number custom error

I am new to asp.net and I have a problem. When the users insert in a editor for a decimal field something other than numbers, they get an error "Field name" is not a number. But I don't want them to receive this message I want them to receive another message. I have no problem with this with required and range validators.
Is there any way for me to do this?
I am not refering necessarily to changing the culture just displaying another message.
Thanks.
Hope I understand your, to change RangeValidator ErrorMessage just initialize ErrorMessage parameter:
[Range(0, 100, ErrorMessage = "Some another error message insert here!")]
[RegularExpression("\d", ErrorMessage = "!!!")]
public decimal DecimalField { get; set; }
This is the actual answer:
Create a class CustomClientDataTypeModelValidatorProvider. Copy the code from the MVC sources. Change the method MakeErrorString to output the appropiate message like this:
private static string MakeErrorString(string displayName)
{
return string.Format(
CultureInfo.CurrentCulture,
Core.Resources.Errors.EroareNuENr,
displayName);
}
I couldn't find a way not to copy the code just extend it as it uses this static method.
If anyone knows this please tell me.
Then, in global.asax, I wrote this:
var cdProvider = ModelValidatorProviders.Providers.SingleOrDefault(p => p.GetType().Equals(typeof(ClientDataTypeModelValidatorProvider)));
if(cdProvider != null)
{
ModelValidatorProviders.Providers.Remove(cdProvider);
ModelValidatorProviders.Providers.Add(
new CustomClientDataTypeModelValidatorProvider());
}
so that the flow would actually be routed to my class and not the class in the asp.net MVC dll
I got the idea from here:
Unfortunately this is is not a trivial task. However you can try the following hack...
Better to do this only on essential fields, as this is more code to maintain.
In the controller's action method
if(ModelState.IsValid)
{
// code
}
else
{
if (ModelState["YourField"].Errors.Count > 0)
{
ModelState["YourField"].Errors.Clear();
ModelState.AddModelError("YourField", "Your custom message here");
}
// code
}
You can set ResourceClassKey of ClientDataTypeModelValidatorProvider class to name of a global resource that contains FieldMustBeNumeric key to replace mvc validation error message of number with your custom message. Also key of date validation error message is FieldMustBeDate.
ClientDataTypeModelValidatorProvider.ResourceClassKey="MyResources"; // MyResource is my global resource
See here for more details on how to add the MyResources.resx file to your project:
The field must be a number. How to change this message to another language?
To change the error message you get after server side validation you need to change 'PropertyValueInvalid' key in your resource file and assign the resource file name to DefaultModelBinder.ResourceClassKey. See this question for details: localize default model validation in mvc 2
Look for solution at the end of this page:
http://jwwishart.wordpress.com/2010/03/22/custom-server-and-client-side-required-validator-in-mvc-2-using-jquery-validate/
I checked this in my MVC 3 RTM project and it works well.
... or use jQuery to change to message on the client.
A quick and simple hack for Customize RangeValidator ErrorMessage --"'Field name' is not a number"-- is using RegularExpression
[Range(0.5, 1000, ErrorMessage = "Amount should be in range {1} to {2}.")]
[DataType(DataType.Currency)]
[RegularExpression(#"\d", ErrorMessage = "Amount is not valid.")]
public decimal Amount{ get; set; }
You could implement your own custom validation attribute: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
It seems that since Para's answer MVC evolved and now the ClientDataTypeModelValidatorProvider accepts a ResourceClassKey property. It uses the FieldMustBeNumeric and FieldMustBeNumeric messages specified in your resource class.

Resources