Почему в этом коде «одноразовая ошибка»? - PullRequest
2 голосов
/ 06 марта 2011

Я создаю компонент GWT, который будет вести себя так же, как поле комментариев здесь на stackoverflow и других сайтах. Я пытаюсь зарегистрировать слушателей для событий KeyPress, Change и ONPASTE, которые обновят мою строку состояния с количеством оставшихся символов и т. Д.

Это работает, за исключением того, что он всегда на один символ от фактического количества символов в текстовой области. Я установил максимальное количество символов на 10. Когда я набираю первый символ, он по-прежнему говорит: «10 символов осталось». Он не обновляет строку состояния до тех пор, пока я не наберу второй символ, а затем он отключается, он говорит, что при наборе второго символа осталось 9 символов.

Когда я BACKSPACE или DELETE, это также один раз, когда нет символов, он по-прежнему говорит «осталось 9 символов», пока я не нажму BACKSPACE или DELETE второй раз.

Я получаю такое поведение в Firefox, Chrome и Internet Explorer в Windows. Так что я думаю, что не регистрирую что-то правильно.

Я знаю, что это как-то связано с началом событий, но я потратил часы, пытаясь диагностировать это поведение, и у меня кончились идеи.

Здесь я регистрирую обработчики событий, полный код: BoundedTextAreaWithFeedback .

private void registerHandlers()
{
    final BoundedTextAreaWithFeedback outer = this;
    this.textArea.addChangeHandler(new ChangeHandler()
    {
        public void onChange(final ChangeEvent changeEvent)
        {
            outer.validate();
        }
    });
    this.textArea.addKeyPressHandler(new KeyPressHandler()
    {
        public void onKeyPress(final KeyPressEvent keyPressEvent)
        {
            outer.validate();
        }
    });
    this.panel.addFocusHandler(new FocusHandler()
    {
        public void onFocus(final FocusEvent focusEvent)
        {
            outer.textArea.setFocus(true);
        }
    });

    // capture paste events
    this.textArea.sinkEvents(Event.ONPASTE);
}

Вот метод validate().

private boolean validate()
{
    final boolean isValid;
    final int len = this.textArea.getText().length();
    if (len < this.minLength)
    {
        this.status.setText("Enter at least " + this.minLength + " characters.");
        this.status.setStyleName("input-status-underflow");
        isValid = false;
    }
    else if (len > this.maxLength)
    {
        this.status.setText(this.maxLength - len + " characters remaining");
        this.status.setStyleName("input-status-overflow");
        isValid = false;
    }
    else
    {
        this.status.setText(this.maxLength - len + " characters remaining");
        this.status.setStyleName("input-status-ok");
        isValid = true;
    }
    return isValid;
}

Ответы [ 2 ]

2 голосов
/ 06 марта 2011

Я только начал добавлять каждые addXXXHandler() до тех пор, пока один из них не заработал.

this.textArea.addKeyUpHandler(new KeyUpHandler()
{
    public void onKeyUp(final KeyUpEvent event)
    {
        outer.validate();
    }
});

Кажется, что добился цели.

Вот рабочий код , CTRL-V и вставка из контекстного меню теперь также работает.

1 голос
/ 06 марта 2011

Попробуйте использовать DeferredCommand для выполнения кода проверки. Я считаю, что проблема в том, что когда событие запускается, их символ еще не добавляется в текстовую область. Команда DeferredCommand не будет выполняться до тех пор, пока не будут завершены какие-либо ожидающие обработчики событий, что позволяет правильно рассчитать длину текста.

См. этот вопрос для примера использования DeferredCommand.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...