Instant value change handler on a GWT textbox

36,030

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.

Share:
36,030

Related videos on Youtube

Jla
Author by

Jla

Updated on July 09, 2022

Comments

  • Jla
    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
    Jla almost 14 years
    As 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
    Ashwin Prabhu almost 14 years
    Hmmm... Did you figure out a way? Please shares the solution when you do :) Thanks
  • Jla
    Jla almost 14 years
    The 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
    ShabbyDoo over 13 years
    Thanks. 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
    z00bs over 13 years
    What you could do is to hide the content of the TextBox until validation is done. It's really a hack but color: transparent would do the trick...
  • alexandroid
    alexandroid over 12 years
    @z00bs Is this possible to do without extending TextArea and using UiBinder?
  • z00bs
    z00bs over 12 years
    I doubt it since you somehow need to extend the behavior in onBrowserEvent().
  • Renato
    Renato about 12 years
    Great answer, but in recent versions of GWT, DeferredCommand has been deprecated in favour of Scheduler.get().scheduleDeferred(...)
  • z00bs
    z00bs about 12 years
    Thx Renato. Edited my answer.
  • Gal Bracha
    Gal Bracha about 12 years
    Best 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
    Gal Bracha about 12 years
    Better 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
    kroiz almost 12 years
    Instead of extending TextBox you could simply use JSNI like here: stackoverflow.com/a/4018317/193016
  • WORMSS
    WORMSS over 7 years
    This does not account for dragging values into the box, also triggers on left/right keyrelease, ctrl keyrelease
  • Bikas Katwal
    Bikas Katwal over 7 years
    true, this will be applicable for typing which includes text. I guess that will serve purpose for this question. Its just a hack ;)
  • Alicia
    Alicia almost 7 years
    Missing "(" after new Type<InputHandler>.
  • Joseph Larson
    Joseph Larson over 6 years
    I get this error during creation: exception 2 (String) : Trying to sink unknown event type input
  • Sir Hackalot
    Sir Hackalot over 5 years
    Excellent answer! Thanks