Это похоже на ошибку. Я только что сообщил об этом здесь https://github.com/vaadin/vaadin-text-field/issues/460
В качестве обходного пути вы можете установить окно resize
listener, которое запускает textArea._updateHeight();
на стороне клиента для запуска обновления высоты. Или вы можете использовать ResizeObserver , но он все еще имеет несколько ограниченную поддержку браузера
Вот наивный пример добавления обходного пути слушателя изменения размера в Flow:
textArea.getElement().executeJs(
"window.addEventListener('resize', function() { $0._updateHeight(); });",
textArea.getElement());
Но вы должны обернуть этот обработчик изменения размера в некоторый базовый c debouncer, чтобы он не запускался _updateHeight()
слишком часто во время изменения размера, чтобы избежать проблем с производительностью.
В качестве альтернативы вы можете сделать это :
UI.getCurrent().getPage().addBrowserWindowResizeListener(event -> {
textArea.getElement().executeJs("this._updateHeight();");
});
Я не уверен, что в addBrowserWindowResizeListener
встроен какой-либо способ устранения неполадок или нет, но я думаю, что это, по крайней мере, вызовет обходные пути сервера при изменении размера, которых, по возможности, следует избегать.
Редактировать:
Вот более универсальный подход, создав новый компонент, расширяющий Vaadin TextArea
и использующий ResizeObserver
в поддерживаемых браузерах (с setInterval
в качестве отступление для других браузеров).
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.textfield.TextArea;
public class CustomTextArea extends TextArea {
private boolean initDone = false;
@Override
protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);
if (!initDone) {
// debounce method borrowed from: https://davidwalsh.name/essential-javascript-functions
getElement().executeJs(
"const debounce = function(func, wait, immediate) {" +
" var timeout;" +
" return function() {" +
" var context = this, args = arguments;" +
" var later = function() {" +
" timeout = null;" +
" if (!immediate) func.apply(context, args);" +
" };" +
" var callNow = immediate && !timeout;" +
" clearTimeout(timeout);" +
" timeout = setTimeout(later, wait);" +
" if (callNow) func.apply(context, args);" +
" };" +
"};" +
"const textArea = $0;" +
"const updateTextAreaHeight = function() { textArea._updateHeight(); };" +
"const debounceTimeout = 50;" +
"const intervalTimeout = 500;" +
"" +
"if (window.ResizeObserver) {" +
" let textAreaDebouncer;" +
" const resizeObserver = new ResizeObserver(debounce(updateTextAreaHeight, debounceTimeout));" +
" resizeObserver.observe(textArea);" +
"} else {" +
" let textAreaWidth = textArea.clientWidth;" +
" window.setInterval(function() {" +
" if (textAreaWidth !== textArea.clientWidth) {" +
" updateTextAreaHeight();" +
" textAreaWidth = textArea.clientWidth;" +
" }" +
" }, intervalTimeout);" +
"}", getElement());
initDone = true;
}
}
}
Тогда просто используйте это CustomTextArea
вместо TextArea
, и оно должно работать.