Enhance Vaadin 14: Automatically adjust TextArea size when window is resized

Using Vaadin 14.1.19 in a project called "My Starter Project," I attempted to create a TextArea that supports multiple lines. Initially, everything seemed fine, but upon resizing the TextArea, it failed to adjust the number of visible lines. Here is the code snippet:

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);
    }
}

Upon initially opening the view with a wide window, it appears as expected:

However, resizing the window results in only the beginning of the text being readable within the TextArea components, without scroll functionality.

Strangely, only the DIV resizes as anticipated.

Is there a way to ensure that Vaadin's TextArea adapts to window resizes?

Answer №1

It appears that a bug has been identified and reported at this GitHub link

To address this issue, one workaround is to establish a window resize listener that executes textArea._updateHeight(); on the client side to prompt the height adjustment. Alternatively, utilizing a ResizeObserver could be an option, bearing in mind its browser support may have limitations as indicated here.

Here's a simple illustration to implement a resize listener workaround using Flow:

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

It is advisable to envelop this resize handler within a basic debouncer to prevent frequent execution of _updateHeight() during resizing events and evade possible performance concerns.

Another approach would involve:

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

The presence of any built-in debouncing functionality in addBrowserWindowResizeListener is uncertain but it should ideally reduce server round trips triggered by the resizing activity.

Edit:

A more universal technique entails creating a new component that extends Vaadin's TextArea, leveraging ResizeObserver in compliant browsers alongside a fallback mechanism involving setInterval for other browsers.

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;
        }
    }
}

Simply substitute CustomTextArea for TextArea to implement this solution successfully.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting issue with Gulp watch on Node v4.6.0

I'm currently facing a frustrating situation. I had a project up and running smoothly with a functioning gulpfile.js file, everything was perfect until I updated node to version 4.6.0. When I tried to report this issue on Gulp's git repository, t ...

What is the best way to convert a 2D PHP array into a JavaScript array?

I have encountered a problem with a PHP array setup as follows: $output = array(array(1,1,1,1),array(2,2,2,2),array(3,3,3,3)); When I encoded the array to JSON, I received this output: $output = {"1":[1,1,1,1],"2":[2,2,2,2],"3":[3,3,3,3]} My goal is to ...

Using the highcharts-ng library in combination with ng-repeat was successful in creating multiple charts. However, in order to display different data for each chart, the

I need to provide the date either from the view template or possibly from the controller in order for the highchart to display the data specified by the <highchart /> directive. Explanation : <ul> <li ng-repeat="li in list"> ...

Convert a div into a clickable link using JavaScript without using too many classes or any ids

After using shortcodes generated by functions.php in a WordPress parent theme, I have come across the following HTML code: <div class="pricing-table-one left full-width "> <div class="pricing-table-one-border left"> <div class=" ...

JavaScript live search dynamically loads MySQL data into memory

Currently, I have implemented a live search feature through a text box on my website. This feature queries a MySQL database to return matching rows as the user types. However, I have noticed that this has significantly increased the memory load on my datab ...

Issues with Navigating through a Scrollable Menu

I'm having a difficult time grasping the concept and implementing a functional scrolling mechanism. Objective: Develop a large image viewer/gallery where users can navigate through images by clicking arrow keys or thumbnails in a menu. The gallery an ...

What is the process for accessing the theme spacing unit in MUI 5?

In previous iterations of MUI, accessing the theme spacing unit was possible through theme.spacing.unit, with a default output of 8. However, this property has been removed in MUI 5. I am having trouble finding documentation on how to access the theme sp ...

Learn how to instruct ajax to fetch the designated information and retrieve corresponding data from the database based on the selected criteria

Looking for some help with my 2 select boxes. The first box allows users to choose a brand, while the second box should display products from that brand fetched from the database. Unfortunately, I'm not familiar with AJAX and the script provided by a ...

Ways to retrieve a service variable within a delegated function (callback)

I am currently using a service that has a variable which needs to be updated by the service itself. However, I am facing an issue where I cannot access the variable in anonymous or delegated functions. (function() { 'use strict'; angular ...

Tips on hiding specific table rows in two separate tables based on the chosen option from a dropdown menu

How do I hide table rows based on dropdown selection? The first table has a dropdown with two options: Current State and Future State. If I select Current State, I want to show or hide specific rows in the 2nd and 3rd tables. I am using IDs for these row ...

Generate dynamic lines with evolving hues using CSS3

While working on a fresh web project, I came across the need to emphasize my headers (h1, h2, h3, h4) with underlines. My goal is to have these underlines grow and change color dynamically, similar to what can be seen here: . Is there a way to achieve thi ...

Prepare an email message for sending

Currently, I'm working on an app using officejs. My goal is to extract content from an Excel worksheet and insert it into an Outlook email. However, I don't want the email to be automatically sent by the system. Instead, I would like the new emai ...

What is the best way to assign a series of radio buttons to an array within an Angular controller's model?

Let's say I have a controller that contains an array property named 'houses'. I want to use ng-repeat to display this array on a table row with a set of radio buttons (true/false, etc.). How can I ensure that selecting any of these radio but ...

Creating a fetcher that seamlessly functions on both the server and client within Nextjs 13 - the ultimate guide!

My Nextjs 13 frontend (app router) interacts with a Laravel-powered backend through an api. To handle authentication in the api, I am utilizing Laravel Sanctum as suggested by Laravel for SPAs. This involves setting two cookies (a session and a CSRF token) ...

Firebase onSnapshot error when retrieving data from Snapchot

Having trouble with Firebase authentication. Whenever I try to authenticate with Firebase, I encounter this error message: App.js:27 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'onSnapshot') Here is the code sni ...

Is there a challenge in setting up a tag search bar similar to Stack Overflow's?

First and foremost, I apologize for the awkwardly phrased question. The issue at hand is that when the tags exceed the container size, the search option becomes hidden. My goal is to have the search bar adjust dynamically, moving everything back inside the ...

Displaying an iFrame with a height that excludes the header section

My website contains an iframe with a height of 100% and a div positioned above it with a height of 70px. The issue is that the iframe overflows the page, causing the scrollbar to extend beyond the visible area. I am looking for a solution to adjust the ifr ...

Excess padding in Internet Explorer 7 when a table is nested within a div tag

I have exhausted all potential solutions found on the internet and still cannot seem to solve this issue. Here is an example page that highlights the problem: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/l ...

Every single checked value in the checkbox variable

Encountered a small hiccup. Let me explain. In my form, there are 8 checkboxes. The goal is to loop through and capture the value of each checked checkbox using a variable. However, I'm always getting the same value from the first checkbox. Here&apo ...

Refine the pandas Dataframe with a filter on a JavaScript-enabled website

I recently inherited a large software project using Python/Flask on the backend and HTML/Javascript on the frontend. I'm now looking to add some interactivity to one of the websites. I have successfully passed a dataframe to the webpage and can displa ...