Валидация TextField для номера телефона

Пишу валидацию текстового поля для номера телефона на фреймворке CUBA Platform и столкнулся с проблемой. Мне необходимо реализовать мгновенную валидацию, чтобы никакие другие символы кроме цифр не печатались в текстовом поле. Пока что у меня получилось только сделать так, чтобы ненужные символы убирались после того как я уберу фокус с текстового поля (реализовано в виде подписки на событие для поля phoneNumberField).

P.S На регулярку особо не всматривайтесь, пока что она простенькая, но в планах сделать нормальную, которая будет ориентирована на формат российских номеров

xml окна:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
        caption="msg://employeeEdit.caption"
        focusComponent="form"
        messagesPack="com.company.planner.web.screens.employee">
    <data>
        <instance id="employeeDc"
                  class="com.company.planner.entity.Employee">
            <view extends="_local"/>
            <loader/>
        </instance>
    </data>
    <dialogMode height="600"
                width="800"/>
    <layout expand="editActions" spacing="true">
        <form id="form" dataContainer="employeeDc">
            <column width="350px">
                <textField id="personalNumberField" property="personalNumber"/>
                <textField id="fullNameField" property="fullName"/>
                <textField id="positionField" property="position"/>
                <textField id="departmentField" property="department"/>
                <textField id="emailField" property="email"/>
                <textField id="phoneNumberField" property="phoneNumber"/>
            </column>
        </form>
        <hbox id="editActions" spacing="true">
            <button id="commitAndCloseBtn" action="windowCommitAndClose" caption="msg://commitAndCloseBtn.caption"/>
            <button id="closeBtn" action="windowClose" caption="msg://closeBtn.caption"/>
        </hbox>

    </layout>
</window>

Сущность Empolyee:

package com.company.planner.entity;

import com.haulmont.chile.core.annotations.NamePattern;
import com.haulmont.cuba.core.entity.StandardEntity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

@Table(name = "PLANNER_EMPLOYEE")
@Entity(name = "planner_Employee")
@NamePattern("%s|personalNumber")
public class Employee extends StandardEntity {
    private static final long serialVersionUID = -4128883590624779007L;

    @NotNull
    @Column(name = "PERSONAL_NUMBER", nullable = false, unique = true)
    @Pattern(message = "В табельном номере должны содержаться только цифры", regexp = "([0-9]+)")
    private String personalNumber;

    @NotNull
    @Column(name = "FULL_NAME", nullable = false)
    private String fullName;

    @NotNull
    @Column(name = "POSITION_", nullable = false)
    private String position;

    @Column(name = "DEPARTMENT", nullable = false)
    @NotNull
    private String department;

    @Column(name = "EMAIL")
    @Email
    private String email;

    @Column(name = "PHONE_NUMBER")
    private String phoneNumber;

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getPersonalNumber() {
        return personalNumber;
    }

    public void setPersonalNumber(String personalNumber) {
        this.personalNumber = personalNumber;
    }
}

Контроллер EmployeeEdit:

package com.company.planner.web.screens.employee;

import com.haulmont.cuba.gui.components.HasValue;
import com.haulmont.cuba.gui.components.TextField;
import com.haulmont.cuba.gui.screen.*;
import com.company.planner.entity.Employee;
import org.slf4j.Logger;

import javax.inject.Inject;

@UiController("planner_Employee.edit")
@UiDescriptor("employee-edit.xml")
@EditedEntityContainer("employeeDc")
@LoadDataBeforeShow
public class EmployeeEdit extends StandardEditor<Employee> {

    @Inject
    private TextField<String> phoneNumberField;

    protected static final Logger log = org.slf4j.LoggerFactory.getLogger(EmployeeEdit.class);


    @Subscribe("phoneNumberField")
    protected void onPhoneNumberFieldValueChange(HasValue.ValueChangeEvent<String> event) {
        String newValue = event.getValue();
        log.info(newValue);
        if (newValue != null) {
            String validatedValue = newValue.replaceAll("[^0-9]", "");
            if (!newValue.equals(validatedValue)) {
                log.info("In loop");
                log.info(validatedValue);
                phoneNumberField.setValue(validatedValue);
            }
        }
    }


}

Ответы (2 шт):

Автор решения: Qwer

Не очень понятно, почему для номера телефона Вы выбрали тип поля textField, т.к. свойство textField и заключается в том, чтобы позволить вам вводить разные символы, числа, текст и т.д. Есть ли у Вас возможность использовать для ввода номера телефона тип поля numberField? numberField имеет большую часть тех же функций, что и textField , но принимает только числовые входные данные.

→ Ссылка
Автор решения: Mswork6

Проблему решил с помощью использования maskedField. Спасибо всем откликнувшимся за помощь)

→ Ссылка