0

使用 Vaadin 14.1.19 和 Vaadin“我的入门项目”-项目我试图创建一个多行 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);
    }
}

当我用一个宽阔的窗口打开视图时,它看起来像这样很好:

Vaadin 14.1.19 TextArea 在宽屏幕上有很多文本

当我调整窗口大小时,它看起来不像这样,因为只有文本的开头是可读的。我什至无法在 TextAreas 内滚动。

Vaadin 14.1.19 TextArea 在小屏幕上有很多文本

只有 DIV 按我预期的方式调整大小。

如何让 Vaadin 的 TextArea 在窗口调整大小时调整大小?

4

1 回答 1

1

这似乎是一个错误。我刚刚在这里报告了它https://github.com/vaadin/vaadin-text-field/issues/460

作为一种解决方法,您可以设置一个在客户端resize运行的窗口侦听器以触发高度更新。textArea._updateHeight();或者您可以使用ResizeObserver ,但它的浏览器支持仍然有限

这是一个在 Flow 中添加调整大小侦听器解决方法的简单示例:

textArea.getElement().executeJs(
    "window.addEventListener('resize', function() { $0._updateHeight(); });",
    textArea.getElement());

但是您应该将此调整大小处理程序包装在一些基本的去抖动器中,以便在调整大小时它不会运行_updateHeight()太频繁以避免性能问题。

或者,您可以这样做:

UI.getCurrent().getPage().addBrowserWindowResizeListener(event -> {
    textArea.getElement().executeJs("this._updateHeight();");
});

我不确定是否addBrowserWindowResizeListener内置了某种去抖动功能,但我认为这至少会导致服务器在调整大小时往返,如果可能的话,应该避免这种情况。

编辑:

这是一种更通用的方法,它创建了一个扩展 VaadinTextAreaResizeObserver在支持的浏览器中使用的新组件(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它应该可以工作。

于 2020-03-19T09:59:22.713 回答