Eagerly validating forms

Hi,

I wanted to improve UX of one of my example apps. I wanted to implement “eagerly validating form”: I wanted e.g. textfields validations to happen while typing, so that I don’t need to click “Save” just to see the data is invalid. Also, I wanted that Save button to be disabled unless there is really something that has changed and the changed stuff is valid.

I’d guess this kind of functionality is pretty common requirement in RIA apps, but I found it to quite effortful to write. I decided to do that immediately for the first and last time, both at the same time.
Maddon 1.7
now has much improved AbstractForm to implement this kind of form. It currently supports only “detached entities”, but I’m using those anyways in pretty much all my apps.

The usage is pretty simple, just set the flag for eager validation on in e.g.
form views constructor
, everything should then happen automatically. I have only tested it in this example app, but I’d expect it to work pretty well in more complex examples as well.

A live demo is
running here
. Please, try it out and share your improvement ideas. I’d also be interested in tips how you have done this kind of solutions before.

cheers,
matti

This makes me think, CSValidation probably should have a feature to send the value (or text) change to server whenever the success/failure/incomplete status changes. That would make forms even more responsive, as there’s still a bit lag with the eager text change events, and of course the unnecessary server round-trips.

Well, this is of course more reliable, as client-side validation has its security and reliability problems.

I see problems when I slowly type in characters. (About 0.5sec between characters)
The component then misses some of the keystrokes, apparently while doing the validation all input done during this time is lost…

Uh. That happens especially with connection with bit more latency.

I hade to make quite a large changes for a workaround:
https://github.com/mstahv/maddon/commit/58e7931fc171f9bbdacc4fcce91f1b5b5ef1db4d

“While typing validation” now only happens if using MTextField. I need to review my change with fresh eyes before publishing a new version.

The demo contains now a solution that is almost identical with the github status.

cheers,
matti

Hi,

I have recently done some enhancments to my
“eagerly validating form”
. E.g. @NotNull annotations from entities now configures their (UI) field propertly. Improvements should be available if you just update your Maddon to the latest version (1.14).

I’d still like to do some improvements, like make required fields, that are not yet modified, emphasized with some less intrusive color. If you have skills and wills, I’d be happy to pull in your contributions.

cheers,
matti

Matti,
I love the eager validation, but there seems to be a problem with populating the fields when displaying the form. I have a tableview from which the user can select a row to edit. A window is popped, with the form for the contents of the selected row. Neither the save or cancel buttons are enabled. To get either to become enabled, I must delete the contents of one of the fields and re-enter the data.
It seems to me that the cancel button should always be enabled. Unless I type something somewhere, the only way to get out of the sub-window is too click the ‘X’.
Thanks for the great addon.

Hi, glad you like it!

You can override the behaviour by overriding adjustResetButton state function. I did this for one app recently. The default for cancel button is wrong indeeed, in case one opens the form in a dialog window. I created
an issue for this
.

cheers,
matti

Thanks Matti - this works great!

Now, if I could just get this functionality to work in a panel which contains several forms. I don’t display the toolbar for each form, but I would like the validation to “bubble” up from the forms to the panel so that I could enable/disable the save button that is on the panel. Maybe I need to rethink the UX.

Thanks again!

Hi,

I’m not quite sure what you are trying to accomplish. Do you have “one-to-one relations” in your domain model that you want to to combine to one form in UI? Maybe introducing a “ValidityChangedListener” to MBeanFieldGroup/AbstractForm would help? That might be handy in other tasks as well.

cheers,
matti

Matti,
Basically, I have several forms visible in one panel (each form contains data from a different entity, e.g. bill to, ship to…) and I don’t have a tool bar on each form, but I would like the validation for each of those forms to somehow “bubble up” to the panel so I could enable/disable the save button on the panel accordingly. That’s kinda why I said maybe I need to rethink the UX…
A public boolean isValid() method for the form would let me know if I have valid data for each form but not sure how I would dynamically enable/disable my buttons…

Hi,

There is now validity changed listener in github version. Also an isValid cheker. It caches the validity after each user so calling isValid many times is just fine, even if your validators are heavy (~ contains backend checks). I’ll probably cut a new version tomorrow, so it would be awesome if you could give some early feedback before it.

cheers,
matti

What I ended up doing is putting a FieldGroupLIstener in the setEagerValidation method of the MBeanFieldGroup, and when the listener is called, I check isValid() on the beanFieldGroup. If everything in the form is valid (I use a StringLengthValidator on my required fields), then I enable the save button.
I’m guessing what you have done with the Form’s eagervalidation and a validity change listener would be very similar to what I did at the bean level.
I’ll check out the github code tomorrow.
Thanks again Matti.

Hi, yes, the behavious should be pretty much the same.

cheers,
matti

Hi Matti, and thanks for this great addon!

I’m using AbstractForm in the same way illustrated by many of your example projects. I also make use of detached entities, so it fits me really well. However, in some forms I want to use password fields. Is there a method to get eager validation working on password fields?

Best regards,
Marcus

Hi Marcus,

Good suggestion, I haven’t needed password field myself, so I haven’t make a a version of it. But it should be easy, pretty much a clone of MTextField’s relevant parts and a small addition to MBeanFieldGroup. Do you want to try contributing this via github? At least create a new issue to the project page.

cheers,
matti

Thanks for your prompt reply! I have opened an issue on the project page. However, it seems the code should be refactored somehow, since a lot of code would be common to the two components? I have commented on the issue with some thoughts on it, however there must be a more elegant approach.

Br,
Marcus