Instant value change handler on a GWT textbox
Solution 1
You could catch the ONPASTE
event and manually fire a ValueChangeEvent
. Something like this:
public void onModuleLoad() {
final Label text = new Label();
final ExtendedTextBox box = new ExtendedTextBox();
box.addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
text.setText(event.getValue());
}
});
box.addKeyUpHandler(new KeyUpHandler() {
@Override
public void onKeyUp(KeyUpEvent event) {
text.setText(box.getText());
}
});
RootPanel.get().add(box);
RootPanel.get().add(text);
}
private class ExtendedTextBox extends TextBox {
public ExtendedTextBox() {
super();
sinkEvents(Event.ONPASTE);
}
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (DOM.eventGetType(event)) {
case Event.ONPASTE:
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
ValueChangeEvent.fire(ExtendedTextBox.this, getText());
}
});
break;
}
}
}
Tested on firefox 3.6.1.
Solution 2
As a general solution, what works for me (thx to gal-bracha comment):
Generally, GWT does not have classes to handle input event (described here and here). So we need to implement it by ourselves:
Handler class:
import com.google.gwt.event.shared.EventHandler;
public interface InputHandler extends EventHandler {
void onInput(InputEvent event);
}
Event class:
import com.google.gwt.event.dom.client.DomEvent;
public class InputEvent extends DomEvent<InputHandler> {
private static final Type<InputHandler> TYPE = new Type<InputHandler>("input", new InputEvent());
public static Type<InputHandler> getType() {
return TYPE;
}
protected InputEvent() {
}
@Override
public final Type<InputHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(InputHandler handler) {
handler.onInput(this);
}
}
Usage:
box.addDomHandler(new InputHandler() {
@Override
public void onInput(InputEvent event) {
text.setText(box.getText());
}
},InputEvent.getType());
It works on every TextBox value change including pasting using context menu. It does not react on arrows, ctrl, shift etc...
Solution 3
I prefer use Elements
than Widgets
so this my way to handler.
Element input = Document.get().getElementById("my-input");
DOM.sinkBitlessEvent(input, "input");
DOM.setEventListener(input, event -> GWT.log("Event!"));
Solution 4
This has been a major issue for me in the past. The keyupHandler wont work because the copy paste requires a second key press on the paste option which does not fire the event. the best i have been able to do is use the old changelistener not ideal but it does work.
Related videos on Youtube
Jla
Updated on July 09, 2022Comments
-
Jla almost 2 years
I would like to update a text field instantly when typing in a GWT TextBox. My problem is that ValueChangeEvent and ChangeEvent handlers only fire when the TextBox loses focus. I thought about using the KeyPressEvent but then nothing would happen when performing a copy paste with the mouse.
What's the simplest way to do that ?
-
Jla almost 14 yearsAs I said the ChangeHandler only fires once the TextBox loses focus but I would like to update my field instantly (while the user is typing).
-
Ashwin Prabhu almost 14 yearsHmmm... Did you figure out a way? Please shares the solution when you do :) Thanks
-
Jla almost 14 yearsThe behaviour change on lose of focus was accepted after all for the app I was working on. So I never did find a solution and left it aside for the moment. But will update the question if ever I find one.
-
ShabbyDoo over 13 yearsThanks. This worked for me. One thing for others to note is that the deferred command is required because the TextBox does not yet contain the text of interest when the paste event is handled. If you are trying to filter the contents of the text box (in my case, for valid characters), note that a user will momentarily see the pasted text. Anyone know any ways around this? From what I've read, FF does not allow clipboard inspection, but both IE and Webkit do?
-
z00bs over 13 yearsWhat you could do is to hide the content of the
TextBox
until validation is done. It's really a hack butcolor: transparent
would do the trick... -
alexandroid over 12 years@z00bs Is this possible to do without extending TextArea and using UiBinder?
-
z00bs over 12 yearsI doubt it since you somehow need to extend the behavior in
onBrowserEvent()
. -
Renato about 12 yearsGreat answer, but in recent versions of GWT, DeferredCommand has been deprecated in favour of Scheduler.get().scheduleDeferred(...)
-
z00bs about 12 yearsThx Renato. Edited my answer.
-
Gal Bracha about 12 yearsBest thing is to use the input event, But I'm not sure how to access it from gwt. It handles both paste, and keyboard, as it raises when the value actually changes. developer.mozilla.org/en/DOM/DOM_event_reference/input
-
Gal Bracha about 12 yearsBetter to use the input event, But I'm not sure how to access it from gwt. It handles both paste, and keyboard, as it raises when the value actually changes. developer.mozilla.org/en/DOM/DOM_event_reference/input
-
kroiz almost 12 yearsInstead of extending TextBox you could simply use JSNI like here: stackoverflow.com/a/4018317/193016
-
WORMSS over 7 yearsThis does not account for dragging values into the box, also triggers on left/right keyrelease, ctrl keyrelease
-
Bikas Katwal over 7 yearstrue, this will be applicable for typing which includes text. I guess that will serve purpose for this question. Its just a hack ;)
-
Alicia almost 7 yearsMissing "(" after new Type<InputHandler>.
-
Joseph Larson over 6 yearsI get this error during creation: exception 2 (String) : Trying to sink unknown event type input
-
Sir Hackalot over 5 yearsExcellent answer! Thanks