Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OnDemand Validation. #102

Closed
babltiga opened this issue Sep 20, 2021 · 19 comments
Closed

OnDemand Validation. #102

babltiga opened this issue Sep 20, 2021 · 19 comments
Labels
staging Changes available on staging branch to-evaluate To understand if it's worth it, or More info needed, or More investigation needed

Comments

@babltiga
Copy link

Is there a way to force on-demand validation? So say we have several fields which by default are marked as valid and a button that should trigger the validation and the state change ?

@Juke1999
Copy link

That is possible with a workaround: if you attach a listener to the regarding elements and the validator is being applied just before the validation check (on button press) and removed as soon as something changes in the elements.
This is quite inconvenient, but it works. I'm using this for a login window.

@palexdev
Copy link
Owner

Sorry, but I don't quite understand the issue
Validators use bindings, they are automatically evaluated as soon as one of the conditions change or a condition/dependency is added, why would you force the update "programmatically"?

@Juke1999
Copy link

Juke1999 commented Sep 27, 2021

That is true. It makes no sense to force the update, but in some cases it is useful to bind it to a certain element instead of any input. And if you add the binding to a certain element, it keeps on checking for any changes instead of the one event you want to look after.

If I can give you an example:

I want to validate the username only when the user is trying to go to the next stepper. I tried that by using the BooleanBinding to bind it to the onNextProperty of the referenced element.

graphic

But as soon as I leave the loginField, it validates it.

output

@palexdev
Copy link
Owner

palexdev commented Sep 27, 2021

@Juke1999 Ah yes, now I get it, thanks for the example
This is the intended behavior, as in many UI frameworks fields are validated as soon as they lose focus.

I wonder how I could improve it though... I mean, yes I could add a boolean flag to disable this behavior if needed, and you would be able to update the validator manually since they expose an update() method but... is this the right way to do it?

@palexdev palexdev added the to-evaluate To understand if it's worth it, or More info needed, or More investigation needed label Sep 27, 2021
@Juke1999
Copy link

This is one way to do it, yes. But the "to evaluate" flag is perfectly fine, as there have to be different options on how to enable such validation features.
I will take a look myself in the following days and will comment as soon as I've found something promising.

@palexdev
Copy link
Owner

This is one way to do it, yes. But the "to evaluate" flag is perfectly fine, as there have to be different options on how to enable such validation features.
I will take a look myself in the following days and will comment as soon as I've found something promising.

Thank you very much 👍🏻

@Juke1999
Copy link

Alright.
So after spending some time researching I've found out that the easiest solution is to use a boolean flag where you can enable and disable on-demand validation. Of course this behavior should be false by default (so no on-demand validation).
Otherwise you can re-implement the whole (bad) JavaFX validation procedure, where you basically add the same kind of flagging to enable the validation only on certain events.
You can assign me on this issue, if you can need a helping hand.

@palexdev
Copy link
Owner

@Juke1999 are you still interested in this?
I'm currently reviewing the validation API, and I was wondering if you would like to take a look at the new implementation

@Juke1999
Copy link

Sure, I can take a look.

@palexdev
Copy link
Owner

palexdev commented Dec 30, 2021

Sure, I can take a look.

Thanks!
Here's a little demo of the new API: validationdemo.zip

It's very experimental.
There are two validators. One is not automatic, meaning that it doesn't use JavaFX properties and it's also bound to one object type only. It also means that every time you validate an object it's needed to apply the specified predicate to the object which may be a little slower (nothing too noticeable though).
The other one is automatic, meaning that validations are made using JavaFX properties and expressions, so when you query the validator to check its state it is faster since the constraints updates automatically.

I kind of like the base idea of the "Constraint" objects, since it also allows to add many other details to the validation (such as the severity for example).
But to be honest the implementation still doesn't convince me. The automatic validator now is flexible enough to allow the user to decide when to trigger the validation. It can be set to be fully automatic (an example with explanation is given in the ValidationTest class), or can be triggered manually (also in the ValidationTest class, see the button)

I was kind of inspired by this awesome library YAVI, but it's super simplified.

Edit: Oh, I also added some experimental utils, don't know if they will remain the same but they seem to be quite useful

@Juke1999
Copy link

Sure, I can take a look.

Thanks!
Here's a little demo of the new API: validationdemo.zip

It's very experimental.
There are two validators. One is not automatic, meaning that it doesn't use JavaFX properties and it's also bound to one object type only. It also means that every time you validate an object it's needed to apply the specified predicate to the object which may be a little slower (nothing too noticeable though).
The other one is automatic, meaning that validations are made using JavaFX properties and expressions, so when you query the validator to check its state it is faster since the constraints updates automatically.

I kind of like the base idea of the "Constraint" objects, since it also allows to add many other details to the validation (such as the severity for example).
But to be honest the implementation still doesn't convince me. The automatic validator now is flexible enough to allow the user to decide when to trigger the validation. It can be set to be fully automatic (an example with explanation is given in the ValidationTest class), or can be triggered manually (also in the ValidationTest class, see the button)

I was kind of inspired by this awesome library YAVI, but it's super simplified.

Edit: Oh, I also added some experimental utils, don't know if they will remain the same but they seem to be quite useful

Alright.
I will take a look as soon as I'm back from vacation (09.01.) and will keep you updated about it.

@palexdev
Copy link
Owner

palexdev commented Jan 8, 2022

Hello @Juke1999!
I made some little changes to the automatic validator, and I think it could be the final version
Here's the same project, the new demo is ValidationTest2 and the new validator is in the validation2 package
validationdemo.zip

Like I said just minor changes. The constraints are now kept in an observable list rather than a map, I think there's no need to associate constraints to a "name", also it's observable so that when it changes (add/remove constraints) the validator state is updated automatically.
A custom property to track the validator state is not needed anymore. Every constraint updates the validator by calling the update() method which at the end calls onUpdated() and this happens every time, regardless the validator state.
That method calls a BiConsumer which can be specified by the user that accepts a boolean and a List of constraints (so the validator state and the invalid constraints produced by the validate() method)
So basically there are two ways to query the validator. One is automatic and relies on the onUpdated() method, it is as easy as setting the consumer. The other one is just by calling the validate() method which like before returns a List of invalid constraints. Of course if the list is empty the validator state is valid (true) otherwise it's invalid (false).
I think the new validator is very convenient

Edit: Oh I forgot to change one thing in the project. The valid property of the validator must be set to true initially (change the constructor) otherwise controls (such the stepper) querying an empty validator won't proceed since the return value is false

@Juke1999
Copy link

Juke1999 commented Jan 8, 2022

Hello @Juke1999!
I made some little changes to the automatic validator, and I think it could be the final version
Here's the same project, the new demo is ValidationTest2 and the new validator is in the validation2 package
validationdemo.zip

Like I said just minor changes. The constraints are now kept in an observable list rather than a map, I think there's no need to associate constraints to a "name", also it's observable so that when it changes (add/remove constraints) the validator state is updated automatically.
A custom property to track the validator state is not needed anymore. Every constraint updates the validator by calling the update() method which at the end calls onUpdated() and this happens every time, regardless the validator state.
That method calls a BiConsumer which can be specified by the user that accepts a boolean and a List of constraints (so the validator state and the invalid constraints produced by the validate() method)
So basically there are two ways to query the validator. One is automatic and relies on the onUpdated() method, it is as easy as setting the consumer. The other one is just by calling the validate() method which like before returns a List of invalid constraints. Of course if the list is empty the validator state is valid (true) otherwise it's invalid (false).
I think the new validator is very convenient

Edit: Oh I forgot to change one thing in the project. The valid property of the validator must be set to true initially (change the constructor) otherwise controls (such the stepper) querying an empty validator won't proceed since the return value is false

I'm home tomorrow and will have a look at the project. Will keep you updated!

@palexdev
Copy link
Owner

palexdev commented Jan 8, 2022

Yep no hurry, thanks!

I'm currently remaking the demo

@Juke1999
Copy link

Hey @palexdev,
I looked into the validators and they are looking good and are logical. I will write some test cases and will check if it there is anything missing or wrong with it.
Will keep you updated!

@palexdev
Copy link
Owner

Thanks @Juke1999 👍🏻
Looking forward to your feedback so that I can complete the remaining controls and hopefully release version 11.13.0 after so much work

@palexdev palexdev added the staging Changes available on staging branch label Jan 13, 2022
@palexdev
Copy link
Owner

The new Validation API is not available on the staging branch
Will implement changes/suggestions if needed

@Juke1999
Copy link

Alright, it looks good and handles validations fine.
I will be there to help, if there are extensions required.

@palexdev
Copy link
Owner

The new Validation API is now available in the latest release, closing this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
staging Changes available on staging branch to-evaluate To understand if it's worth it, or More info needed, or More investigation needed
Projects
None yet
Development

No branches or pull requests

3 participants