Grails parent child form validation - validation

I have an Invoice
class Invoice{
static hasMany = [lineItems: InvoiceItem]
double total
}
class InvoiceItem{
String description
double price
double qty
}
My issue is with form validation. If a user enters a string or invalid number format in either price or qty I get a
Failed to convert property value of type java.lang.String
to required type double for property price
BUT the error is in the Invoice object NOT in the LineItems object therefore I cannot highlight in RED the form appropriately. (And field value remains at zero when displayed so message is somewhat meaningless to user)
I was thinking of using COMMAND object with String parameters and validating their numeric value but I can't figure how to bind the InvoiceItem List.
What is the appropriate Grails way?
I could do all validation on the client side in javascript but that is not my question

You can do it with command objects. You need to read:
http://blog.peterdelahunty.com/2009/01/cool-way-to-dynamically-add-entries-to.html
command object data binding
Grails command object data binding
http://grails.1312388.n4.nabble.com/validating-nested-command-objects-td1346994.html

Related

Update picklist value to null with Sdk.Sync.Update does nothing

Is it possible to update a record's attribute of picklist type with null by using Sdk.Sync.Update? It's not working for me.
Here's what I do:
var detailsObj = updatedDetailsObj; // I get updatedDetailsObj from previous logic, not shown here
var operation = new Sdk.Entity("kcl_operation");
operation.setId(operationId, false); // I have operationId from previous logic, not shown here
operation.addAttribute(new Sdk.String("op_updatedAccount", detailsObj.UpdatedAccount)); // works, get updated
operation.addAttribute(new Sdk.OptionSet("op_updatedExplanation", null)); // doesn't get updated
Sdk.Sync.update(operation);
After the completion of Sdk.Sync.update, the string field get updated, but the picklist field is left with its previous value, instead of null.
I also took a look inside the XML being sent inside Sdk.Sync.update, and indeed, it lacks the pair of "op_updatedExplanation" and null.
How can make it work?
Added:
I'm not doing it inside a form but inside a grid page, so that the user checks several records and I need to make the update on all of them.
standard CRM SDK code (assuming entity name and field name):
Entity operation = new Entity("kcl_operation");
operation.Id = operationId;
operation["op_updatedexplanation"] = null;
service.Update(operation);
where service is an IOrganizationService instance
Please use this snippet to set value as null.
Xrm.Page.getAttribute("op_updatedexplanation").setValue(null);
This will just set the value in the form. You may have to save the form to see the value getting stored in database.
Xrm.Page.data.entity.save();
If the control is disabled - you have to set the submitmode attribute also.
Xrm.Page.getAttribute("op_updatedexplanation").setSubmitMode("always");

Get multiple selected values from list in arrraylist on select in Spring MVC

I have a bean class named AnnouncementDetails having attributes
Now on submit i want to get the values of the selected users in selectedUsers Arraylist. Any idea how to do that? ..............................................
Change datatype to String array and then convert to arraylist by Arrays.asList(selectedUsers).
String [] selectedUsers

grails integer field default validation

I have a grails domain class that looks like:
class Person {
String name
int age
}
When I show the default "create" view (using scaffolding), the age field shows as a required field (with an asterisk next to it). Is there a way to make it show up as non-required and default to blank?
I've tried adding
constraints = {
age blank:true, nullable:true
}
This results in the field being allowed to be empty but it still shows up with the asterisk next to it.
An int is a primitive type and cannot be blank. You would have to change it to an Integer, then a null value would mean that it's blank.

Propel ORM Version 1.6.4 -understanding validators

(reworded the question hours later to be more descriptive)
I need a little advice on understanding Propel setters/validators in a standalone (non-framework) development.
The documentation on validation states:
Validators help you to validate an input before persisting it to the database.
... and in validator messages we can provided coherent advice on where users can correct entries that don't pass Propel validation.
The sample usage of a validator reads:
$user = new User();
$user->setUsername("foo"); // only 3 in length, which is too short...
if ($objUser->validate()) {
...
The problem I have found with this is 'what if you cannot setXXX() in order to validate it?'
I have a column type DATE and I invite a visitor to enter a date in a web form. They mistype the date and submit 03/18/20q2
I would hope that one of my custom validators would be able to report a validator message and return the form once more to the user to be amended, however this occurs first:
Fatal error: Uncaught exception 'PropelException' with message 'Error parsing date/time value: '03/18/20q2' [wrapped: DateTime::__construct() [<a href='datetime.--construct'>datetime.--construct</a>]: Failed to parse time string (03/18/aaa) at position 5 (/):
In my tests I couldn't get any simple or CustomValidator to fire once I'd written (for example):
$event= new Event();
$event->setDateStart($form_value_for_date); // where values is "03/18/20q2"
I understand why this is so - it would not make sense to be able to create and try to manipulate a new object if you cannot rely on its fields, even before you save it.
The dilemma this gives me is:
If a fatal error can result from invalid entry preventing Propel validation from handling it for me (and therefore the user) and sending back a useful message, should I bother with Propel validation as well as my own security/courtesy validation ?
I cannot find any mention in the docs of what happens if you give Propel - for whatever reason - a value it doesn't anticipate for the field, or how to handle it.
I do hope this makes sense and that someone can point me at a method that will mean I only need to validate input in one place.
I've hacked together a rough ready solution that will allow me to:
Pre-validate a field against a CustomValidator without setting it in the new object
Retrieve the validator's message for return to the user
I take the form input, sanitise it of course, and then create an object:
$event = new Event();
With my user form in mind, I then pre-check the field I know will fatally fall over if the content's bad, and only set the field in my new object if it would validate:
if ($check = $event->flightCheckFail('StartingDate','DateValidator',$sanitisedFormVal))
echo $check;
else
$event->setStartingDate($sanitisedFormVal);
Method flightCheckFail() will return false if the data from the form would validate against the field, it returns the validator's error message if it would fail.
The method's added to my Event class as follows. Its arguments are the field name, the class of the CustomValidator (which simply runs an strtotime check), and the sanitised form value:
public function flightCheckFail($name,$validatorClass,$value) {
$colname = $this->getPeer()->getTableMap()->getColumnByPhpName($name)->getName();
$validators = $this->getPeer()->getTableMap()->getColumn($colname)->getValidators();
foreach($validators as $validatorMap)
if ($validatorMap->getClass() == $validatorClass) {
$validator = BasePeer::getValidator($validatorMap->getClass());
if ( $validator->isValid($validatorMap, $value) === false)
$failureMessage = $validatorMap->getMessage();
} // if $validatorMap->getClass() == $validatorClass
if($failureMessage)
return $failureMessage;
else
return false;
}
I should be able to use this to work around handling dates in forms, but I'll need to check what other types in Propel might require this sort of handling.
I can stop the form handling wherever this reports a validator error message and send it back. When the user enters valid data, Propel (and normal Propel Validation) gets to continue as normal.
If anyone can improve on this I'd love to see your results.
You could also use a MatchValidator, with a date RegExp, no need for extra functions

StringLength vs MaxLength attributes ASP.NET MVC with Entity Framework EF Code First

What is the difference in behavior of [MaxLength] and [StringLength] attributes?
As far as I can tell (with the exception that [MaxLength] can validate the maximum length of an array) these are identical and somewhat redundant?
MaxLength is used for the Entity Framework to decide how large to make a string value field when it creates the database.
From MSDN:
Specifies the maximum length of array
or string data allowed in a property.
StringLength is a data annotation that will be used for validation of user input.
From MSDN:
Specifies the minimum and maximum
length of characters that are allowed
in a data field.
Some quick but extremely useful additional information that I just learned from another post, but can't seem to find the documentation for (if anyone can share a link to it on MSDN that would be amazing):
The validation messages associated with these attributes will actually replace placeholders associated with the attributes. For example:
[MaxLength(100, "{0} can have a max of {1} characters")]
public string Address { get; set; }
Will output the following if it is over the character limit:
"Address can have a max of 100 characters"
The placeholders I am aware of are:
{0} = Property Name
{1} = Max Length
{2} = Min Length
Much thanks to bloudraak for initially pointing this out.
Following are the results when we use both [MaxLength] and [StringLength] attributes, in EF code first. If both are used, [MaxLength] wins the race. See the test result in studentname column in below class
public class Student
{
public Student () {}
[Key]
[Column(Order=1)]
public int StudentKey { get; set; }
//[MaxLength(50),StringLength(60)] //studentname column will be nvarchar(50)
//[StringLength(60)] //studentname column will be nvarchar(60)
[MaxLength(50)] //studentname column will be nvarchar(50)
public string StudentName { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
All good answers...From the validation perspective, I also noticed that MaxLength gets validated at the server side only, while StringLength gets validated at client side too.
One another point to note down is in MaxLength attribute you can only provide max required range not a min required range.
While in StringLength you can provide both.
MaxLengthAttribute means Max. length of array or string data allowed
StringLengthAttribute means Min. and max. length of characters that are allowed in a data field
Visit http://joeylicc.wordpress.com/2013/06/20/asp-net-mvc-model-validation-using-data-annotations/
You can use :
[StringLength(8, ErrorMessage = "{0} length must be between {2} and {1}.", MinimumLength = 6)]
public string Address { get; set; }
The error message created by the preceding code would be "Address length must be between 6 and 8.".
MSDN: https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-5.0
I have resolved it by adding below line in my context:
modelBuilder.Entity<YourObject>().Property(e => e.YourColumn).HasMaxLength(4000);
Somehow, [MaxLength] didn't work for me.
When using the attribute to restrict the maximum input length for text from a form on a webpage, the StringLength seems to generate the maxlength html attribute (at least in my test with MVC 5). The one to choose then depnds on how you want to alert the user that this is the maximum text length. With the stringlength attribute, the user will simply not be able to type beyond the allowed length. The maxlength attribute doesn't add this html attribute, instead it generates data validation attributes, meaning the user can type beyond the indicated length and that preventing longer input depends on the validation in javascript when he moves to the next field or clicks submit (or if javascript is disabled, server side validation). In this case the user can be notified of the restriction by an error message.

Resources