Vaadin 14:调整大小后调整 TextArea window
Vaadin 14: Resize TextArea after resizing window
使用 Vaadin 14.1.19 和 Vaadin "My Starter Project"-project 我试图创建一个多行 TextArea。乍一看它工作正常,但在调整 TextArea 大小时,它不会调整行数。
这是我的代码:
package com.packagename.myapp;
import org.springframework.beans.factory.annotation.Autowired;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;
@Route(layout = DesktopLayout.class)
@PWA(name = "Project Base for Vaadin Flow with Spring", shortName = "Project Base")
public class MainView extends VerticalLayout {
public MainView(@Autowired MessageBean bean) {
String loremIpsum = "Lorem ipsum dolor sit amet, [....].";
TextArea readOnlyTA = new TextArea();
readOnlyTA.setLabel("Read-only");
readOnlyTA.setWidth("1500px");
readOnlyTA.setMaxWidth("80vw");
readOnlyTA.setValue(loremIpsum);
readOnlyTA.setReadOnly(true);
add(readOnlyTA);
TextArea readWriteTA = new TextArea();
readWriteTA.setLabel("normal");
readWriteTA.setWidth("1500px");
readWriteTA.setMaxWidth("80vw");
readWriteTA.setValue(loremIpsum);
add(readWriteTA);
Div readOnlyDiv = new Div();
readOnlyDiv.setWidth("1500px");
readOnlyDiv.setMaxWidth("80vw");
readOnlyDiv.add(loremIpsum);
add(readOnlyDiv);
}
}
当我用宽 window 打开视图时,它看起来像这样很好:
当我调整 window 大小时,它看起来不太好,因为只有文本的开头是可读的。
我什至无法在 TextAreas 中滚动。
只有 DIV 调整大小符合我的预期。
如何让 Vaadin 的 TextArea 以 window 调整大小?
这似乎是一个错误。我刚刚在这里报告了 https://github.com/vaadin/vaadin-text-field/issues/460
作为解决方法,您可以在客户端设置 window resize
侦听器 运行s textArea._updateHeight();
以触发高度更新。或者您可以使用 ResizeObserver but it still has somewhat limited browser support
这是一个在 Flow 中添加调整大小侦听器解决方法的简单示例:
textArea.getElement().executeJs(
"window.addEventListener('resize', function() { [=10=]._updateHeight(); });",
textArea.getElement());
但是您应该将此调整大小处理程序包装在一些基本的去抖动器中,这样它就不会 运行 _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 = [=12=];" +
"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
就可以了。
使用 Vaadin 14.1.19 和 Vaadin "My Starter Project"-project 我试图创建一个多行 TextArea。乍一看它工作正常,但在调整 TextArea 大小时,它不会调整行数。 这是我的代码:
package com.packagename.myapp;
import org.springframework.beans.factory.annotation.Autowired;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;
@Route(layout = DesktopLayout.class)
@PWA(name = "Project Base for Vaadin Flow with Spring", shortName = "Project Base")
public class MainView extends VerticalLayout {
public MainView(@Autowired MessageBean bean) {
String loremIpsum = "Lorem ipsum dolor sit amet, [....].";
TextArea readOnlyTA = new TextArea();
readOnlyTA.setLabel("Read-only");
readOnlyTA.setWidth("1500px");
readOnlyTA.setMaxWidth("80vw");
readOnlyTA.setValue(loremIpsum);
readOnlyTA.setReadOnly(true);
add(readOnlyTA);
TextArea readWriteTA = new TextArea();
readWriteTA.setLabel("normal");
readWriteTA.setWidth("1500px");
readWriteTA.setMaxWidth("80vw");
readWriteTA.setValue(loremIpsum);
add(readWriteTA);
Div readOnlyDiv = new Div();
readOnlyDiv.setWidth("1500px");
readOnlyDiv.setMaxWidth("80vw");
readOnlyDiv.add(loremIpsum);
add(readOnlyDiv);
}
}
当我用宽 window 打开视图时,它看起来像这样很好:
当我调整 window 大小时,它看起来不太好,因为只有文本的开头是可读的。 我什至无法在 TextAreas 中滚动。
只有 DIV 调整大小符合我的预期。
如何让 Vaadin 的 TextArea 以 window 调整大小?
这似乎是一个错误。我刚刚在这里报告了 https://github.com/vaadin/vaadin-text-field/issues/460
作为解决方法,您可以在客户端设置 window resize
侦听器 运行s textArea._updateHeight();
以触发高度更新。或者您可以使用 ResizeObserver but it still has somewhat limited browser support
这是一个在 Flow 中添加调整大小侦听器解决方法的简单示例:
textArea.getElement().executeJs(
"window.addEventListener('resize', function() { [=10=]._updateHeight(); });",
textArea.getElement());
但是您应该将此调整大小处理程序包装在一些基本的去抖动器中,这样它就不会 运行 _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 = [=12=];" +
"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
就可以了。