-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi
Right now I didn't have any issues in learning how to use ZK - I focused on MVVM mainly.
But lately I spent some time reading about validators and played around with test code and to be honest - I can not see a "clear path" how to use form validation.
As far as I can tell MVVM uses valitators to validate input - VM provides a instance of AbstractValidator and it does all the validation like explained here. There are some pros and cons with property bindings and the "save before" approach - well, not to hard to understand but a "lot" of code to write.
On the other side there is an "easy" way to get form validation by applying
constraint='.....' to an input field - realllyyyy easy.
So here a few questions:
1.) Why are there no examples with MVVM and constraint="..." - also see nr. 2
2,) It seems to me the validator is much more effort - think of preventing an empty textfield
<textbox constraint="no empty"/>
versus
<textbox value="@load(...) @validator(vm.quantityValidator)" />
plus additional java code for validating the same basic thing
public Validator getQuantityValidator(){ return new AbstractValidator(){ public void validate(ValidationContext ctx) { Integer nr = (Integer)ctx.getProperty().getValue(); if(nr==null || nr<=0){ addInvalidMessage(ctx, "must be larger than 0"); } } }; }
3.) Is there an way to prevent a command execution (eg onSave) when "constraint" still has errors or does MVVM ALWAYS have to have a server side validator implementation in MV?
Maybe I am just completly on the wrong path ... any comments?
BR
juergenmw
Hello juergenmw,
I have some thoughts regarding 2nd question: as far as I understand from Javadoc for ClientConstraint some validations are performed on a client side. It is faster and lighter but generally it's not reliable way because an attacker can easily change validation logic or disable it all.
However I join your question and would like to know the difference between server side constraints and validators (which are always server-side, as far as I understand)
Thank you,
Anton.
Currently I use the following approach:
- use constraints where possible for single field validation; I also do not see the advantage here
- use form binding which triggers another validation at submit phase (i.e also the constraints are revalidated, similar to DataBinder.saveAll())
- for more complex validations (i.e. relations of input fields) I use the new validator approach (you have the chance to show mulitple error messages with one validation); this validator is only connected with form binding (i.e. submit)
But I am also missing a general statement especially for simple cases like "no empty" or "no negative".
Hi antonko
Sure - client Side validation is insecure by design.
I guess I was confused because there is "SimpleConstraint" and "ClientConstraint" which indicated (to me) that simpleConstraint is done server side which is wrong - unfortunately I did not read the javadoc at length, my mistake.
Regarding your question - I would assume (please correct me) that server side constraint just "checks" for the given format/content and behaves like client constraint and returns a message (or JS code) which is being displayed. It can be used when client and server's implementation (eg. regexp) differ.
Whereas validator (server side only) has some automatism to store error messages to the binder (see Validation Message Holder). The messages can be accessed by the client via field id and validationMessages="@id('vmsgs')"
Maybe someone else can explain it better.
I would like to break down my initial question - why is there no "default" server side validation implementations?
I'd assume 90% of the fields follow the same rules:
* min/max int
* min/max string length
* no empty
* email
* ....
Despite ZK's validator approach is quite flexible those default checks will be implemented over and over again (even though they are not very complicated to implement). E.g. as a beginner I was simply searching for a "EmailValidator" implementation under org.zkoss.*
BR
juergenmw
@Matze2 - when is it possible to use constraint? Since it seems this is done on client side this is never a secure way to validate input (meaning: protecting Bean/DB from disallowed values). I assume you just use it to get the user message immediatly, real validation is done before saving the middle object/bean.
What was the standard way of server side validation before ZK6 (MVVM) when only using MVC?
I don't think that it is only checked on the client side,see SimpleConstraint.validate():
public void validate(Component comp, Object value) throws WrongValueException { if (value == null) { if ((_flags & NO_EMPTY) != 0) throw wrongValue(comp, MZul.EMPTY_NOT_ALLOWED); } else if (value instanceof Number) { if ((_flags & (NO_POSITIVE|NO_NEGATIVE|NO_ZERO)) == 0) return; //nothing to check final int cmp = compareTo((Comparable)value, Classes.coerce(value.getClass(), null, false)); //compare to zero if (cmp > 0) { if ((_flags & NO_POSITIVE) != 0) throw wrongValue(comp, getMessageForNumberDenied()); } else if (cmp == 0) { if ((_flags & NO_ZERO) != 0) throw wrongValue(comp, getMessageForNumberDenied()); } else { if ((_flags & NO_NEGATIVE) != 0) throw wrongValue(comp, getMessageForNumberDenied()); } } else if (value instanceof String) { final String s = (String)value; if ((_flags & NO_EMPTY) != 0 && s.length() == 0) throw wrongValue(comp, MZul.EMPTY_NOT_ALLOWED); if (_regex != null && !_regex.matcher(s != null ? s: "").matches()) throw wrongValue(comp, MZul.ILLEGAL_VALUE); if ((_flags & STRICT) != 0) { if (s.length() > 0 && comp instanceof Combobox) { for (Iterator it = ((Combobox)comp).getItems().iterator(); it.hasNext();) { final Comboitem ci = (Comboitem)it.next(); if(!ci.isDisabled() && ci.isVisible() && s.equalsIgnoreCase(ci.getLabel())) return; } throw wrongValue(comp, MZul.VALUE_NOT_MATCHED); } } } else if (value instanceof Date) { if ((_flags & (NO_FUTURE|NO_PAST|NO_TODAY)) == 0) return; final Date date = Dates.beginOfDate((Date)value, null); final int cmp = date.compareTo(Dates.today()); if (cmp > 0) { if ((_flags & NO_FUTURE) != 0) throw wrongValue(comp, getMessageForDateDenied()); } else if (cmp == 0) { if ((_flags & NO_TODAY) != 0) throw wrongValue(comp, getMessageForDateDenied()); } else { if ((_flags & NO_PAST) != 0) throw wrongValue(comp, getMessageForDateDenied()); } } }
Asked: 2012-05-05 16:13:30 +0800
Seen: 621 times
Last updated: May 09 '12