I had some little sample I wanted to write where I had a TextField that restricted input. Maybe somebody else out there has already figured out how to do this elegantly, but I hadn’t and thought it would be worth a small post to demonstrate the technique.

Within the TextInputControl is a Content, which actually models the TextInputControl’s content. So for example, this is where we strip out newlines and such if you paste a String into a TextField that contains such characters, but in TextArea we allow those sorts of modifications. There is a protected getContent() method, so in theory a subclass of TextInputControl can manipulate the content directly, although in the case of TextField, it does not.

In fact, the only places in all the code that actually modify the TextField’s text is in the replaceText and replaceSelection methods defined on TextInputControl. So all you have to do is subclass TextField and override these two methods.

field = new TextField() {
    @Override public void replaceText(int start, int end, String text) {
        // If the replaced text would end up being invalid, then simply
        // ignore this call!
        if (!text.matches("[a-z]")) {
            super.replaceText(start, end, text);
        }
    }

    @Override public void replaceSelection(String text) {
        if (!text.matches("[a-z]")) {
            super.replaceSelection(text);
        }
    }
};

In the future we may want to add a more specific method (maybe called “accept” which takes the proposed new string after the modification) so that in the off chance that TextField or TextInputControl ends up modifying the content from some additional methods beyond these two, you could still have a reliable way to reject invalid input. However for the time being, this should work just fine!