Так вот мое решение (основано на большой обратной связи Давида):
Во-первых, существует ограничение в TextInputCell в том, что он не может обрабатывать родные keypress
события, так что мне пришлось создать почти точную копию класса и добавьте тип события keypress
в конструктор, где он передает типы событий, которые ячейка может обрабатывать супер-конструктору. Назовем этот класс KeyPressableTextInputCell
. Смотрите эту тему, где я обсуждал это решение: Why isn't the keypress event being sent to GWT's TextInputCell.onBrowserEvent() method?
Затем я создал класс MaskedTextInputCell, который переопределяет метод onBrowserEvent()
и предотвращает недопустимые нажатия клавиш, как они набирают, а также проверяет общий вид поля. Например, действительные денежные нажатия клавиш составляют 0-9 и десятичную точку. Общая форма должна быть только с числами с одной десятичной точкой. Обе эти проверки выполняются с использованием интерфейса стратегии, который я вызывал ValidationStrategy
и помещался непосредственно в MaskedTextInputCell.
public class MaskedTextInputCell extends KeyPressableTextInputCell {
public interface ValidationStrategy {
public boolean matches(String valueToCheck);
}
private ValidationStrategy overallFormValidationStrategy;
private ValidationStrategy validKeystrokeValidationStrategy;
public MaskedTextInputCell(ValidationStrategy overallFormValidationStrategy,
ValidationStrategy validKeystrokeValidationStrategy) {
this.overallFormValidationStrategy = overallFormValidationStrategy;
this.validKeystrokeValidationStrategy = validKeystrokeValidationStrategy;
}
@Override
public void onBrowserEvent(Element parent, String value, Object key, NativeEvent event,
ValueUpdater<String> valueUpdater) {
super.onBrowserEvent(parent, value, key, event, valueUpdater);
if ("keypress".equals(event.getType())) {
String keystroke = String.valueOf((char) event.getCharCode());
handleInvalidKeystroke(keystroke, event);
} else if ("blur".equals(event.getType()) || "keyup".equals(event.getType())) {
String valueInInputElement = getInputElement(parent).getValue();
handleInvalidOverallForm(valueInInputElement);
}
}
protected void handleInvalidOverallForm(String valueOfEntireField) {
if (!overallFormValidationStrategy.matches(valueOfEntireField)) {
//You could fire an event here to turn the cell red...
GWT.log("Invalid form.");
}
}
protected void handleInvalidKeystroke(String keystroke, NativeEvent event) {
if (!validKeystrokeValidationStrategy.matches(keystroke)) {
GWT.log("Invalid keystroke.");
event.preventDefault();
}
}
}
Затем я создал регулярную реализацию экспрессии ValidationStrategy:
public class RegularExpressionValidationStrategy implements MaskedTextInputCell.ValidationStrategy {
private String regularExpression;
public RegularExpressionValidationStrategy(String regularExpression) {
this.regularExpression = regularExpression;
}
@Override
public boolean matches(String valueToCheck) {
return valueToCheck.matches(regularExpression);
}
}
Теперь, я могу сделать что-то вроде этого, чтобы создать поле денег:
public class MonetaryTextInputCell extends MaskedTextInputCell {
public MonetaryTextInputCell() {
super(new RegularExpressionValidationStrategy("[0-9.]"),
new RegularExpressionValidationStrategy("^[0-9.][0-9]*[0-9.]?[0-9]*$"));
}
}
Отлично! У меня наконец-то есть работа с захватом событий keyup/keydown и обрезкой, но preventDefault работает намного лучше! Я отправлю свое окончательное решение в виде отдельного ответа, но я соглашусь с вами. –