Q:

JavaFX TextField OnKeyTyped Not Working Properly

Given
JavaFX App, Input TextField and Submit Button
There's an EventHandler attached to the TextField so that if no text is typed, the Button should be disabled and vice versa.
Here's my code: 
button.setDisable(true); // initially disabled
textField.setOnKeyTyped(new EventHandler<KeyEvent>() {
       @Override
       public void handle(KeyEvent event) {
            if (textField.getText().trim().isEmpty()) { // if blank textfield
                 button.setDisable(true);
            } else {
                 button.setDisable(false); 
             }
        }
});

Both Controls are initialized properly. And as far as I know, the difference between KeyTyped and KeyPressed/Released is that Typed is for characters that can actually be typed and shown; whereas Pressed/Released is for any keyboard key including Ctrl, Alt...
Problem
I type into the textField one character, the button is still disabled! If I type 2 characters and more and it becomes enabled!
However, when if I do the following:
button.setDisable(true);
textField.setOnKeyReleased(
    /*
     exact same code as above
    */
);

my problem will be solved.
Question
WHY? Where's the flaw in my code? Why doesn't KeyTyped work as expected?

A:

The problem is: in the time when you handle the KeyEvent, it is not sure that the textProperty of your TextField was updated or not.
Cleaner and safer approach to add a listener for the textProperty of the TextField to be notified when the text of the TextField changes. Imagine also the usecase that the user pasted some content: in this case there is no KeyEvent at all, therefore your Button remains disabled.
Using a listener on textProperty()
button.setDisable(true);
textField.textProperty().addListener((obj, oldVal, newVal) -> {

    if (newVal.trim().isEmpty()) { // if blank textfield
         button.setDisable(true);
    } else {
         button.setDisable(false); 
     }
});

... or even shorter ...
button.setDisable(true);
textField.textProperty().addListener((obj, oldVal, newVal) -> button.setDisable(newVal.trim().isEmpty()));

But, the much cleaner solution to use binding between the disableProperty of the Button and the textProperty of the TextField.
Using a binding between disableProperty and textProperty
BooleanBinding textIsEmpty = Bindings.createBooleanBinding(() -> textField.getText().trim().isEmpty(), textField.textProperty());
button.disableProperty().bind(textIsEmpty);

