Reputation: 1049
I'm new to JavaFx, i'm creating an application where the user has to fill out some forms and i wanted to "pre validate" them with bindings. Simple stuff like none of the elements can be empty or some of them can only contain numbers. Here is what i have so far:
saveBtn.disableProperty().bind(Bindings.when(
departureHourText.textProperty().isNotEqualTo("")
.and(isNumber(departureHourText.getText())))
.then(false)
.otherwise(true));
Here is my isNumber
method:
private BooleanProperty isNumber(String string) {
return new SimpleBooleanProperty(string.matches("[0-9]+"));
}
But the button is keep being disabled no matter what i type into the TextField.
Any help is greatly appreciated.
UPDATE
When i evaluate this expression: departureHourText.textProperty().isNotEqualTo("")
the result will be : BooleanBinding [invalid]
Upvotes: 6
Views: 8463
Reputation: 41
I wonder if the expression could be written without the when
? If (x) then false else true;
seems to be redundant and could maybe be simplified using not (x)
...
There may be an option to just use the .not()
instead as in:
.bind(departureHourText.textProperty().isNotEqualTo("").and(patternTextAreaBinding(departureHourText,numbers))).not())
Upvotes: 0
Reputation: 674
Your expression is a bit off.
Let's try to test both parts of your logical statement:
saveBtn.disableProperty().bind(Bindings.when(
departureHourText.textProperty().isNotEqualTo(""))
.then(false)
.otherwise(true));
The above code works correctly. When you add a string to the text box, you'll get a button toggle event.
saveBtn.disableProperty().bind(Bindings.when(
isNumber(departureHourText.getText()))
.then(false)
.otherwise(true));
The above code makes it so that the button is always stuck as disabled. Let's investigate why.
Let's add a print statement into the method isNumber():
private BooleanProperty isNumber(String string) {
System.out.println("This was called");
return new SimpleBooleanProperty(string.matches("[0-9]+"));
}
If we look at when this is executed when we start typing, we find that it is only called when we initially declare the binding! This is because your method does not know when to be called, so the binding only ever sees it initially, when it is false because there are no numbers in the field.
What we need to do is find a way so that when our text property gets updated, it knows to change states. If we look at our isNotEqualTo() as an example, we find that we will probably want to look for a way to make a new BooleanBinding somehow.
Now, I found a function and I modified from a github link (https://gist.github.com/james-d/9904574). The link indicates how we can create a new BooleanBinding from a regex pattern.
First, let's make a new pattern:
Pattern numbers = Pattern.compile("[0-9]+");
Then create the binding function:
BooleanBinding patternTextAreaBinding(TextArea textArea, Pattern pattern) {
BooleanBinding binding = Bindings.createBooleanBinding(() ->
pattern.matcher(textArea.getText()).matches(), textArea.textProperty());
return binding ;
}
So with that we can now do what you wanted to do! We just change out your previous function for our new patternTextAreaBinding(TextArea textArea, Pattern pattern) function and pass in our two values, the textArea you want to keep track of and the Pattern you want to adhere to (I called the pattern above numbers).
saveBtn.disableProperty().bind(Bindings.when(
departureHourText.textProperty().isNotEqualTo("")
.and(patternTextAreaBinding(departureHourText,numbers)))
.then(false)
.otherwise(true));
Hope that helps!
Upvotes: 17