I need to process some data and show processing logs on a webpage. (Around 300 lines of text).
I tried to use labels. At first it worked fine - page became scrollable and all text could be seen. But after around 100 labels page became unresponsive.
How to manage this task?
(I tried to look for some other components on webcomponents.org but couldn't find anything.)

- 467
- 1
- 6
- 23
-
Have you tried using a TextArea? – brijesh Aug 21 '18 at 05:48
-
@btreport No, because I can't find a way to just append text to TextArea and doing `textArea.setValue(textArea.getValue() + newLineOfText);` for 300 times doesn't seem to me like a good solution. – John Aug 21 '18 at 05:57
-
Not really sure but if you think about DOM thats the way 2-way binding works, you update an element on the DOM when a values is updated. – brijesh Aug 21 '18 at 06:10
2 Answers
TextArea
I tried one of the approaches mentioned in Answer by Leif Åstrand, using TextArea
.
When I preload with 300 short lines, no problem. Clicking a button to add 10 more lines at a time works without a hitch. Using the web browser’s window scroll bar to scroll up and down works smoothly.
I used Vaadin 10.0.4 with Java 10.0.1 (Zulu by Azul Systems), in browser Safari 11.1.2 on macOS High Sierra on an external 4K monitor hooked up to a MacBook Pro Retina.
Here is the entire Vaadin app.
package com.basilbourque.example;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dependency.HtmlImport;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.router.Route;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* The main view contains a button and a template element.
*/
@HtmlImport ( "styles/shared-styles.html" )
@Route ( "" )
public class MainView extends VerticalLayout {
TextArea textArea;
// Constructor.
public MainView () {
this.setWidth( "100%" );
this.textArea = new TextArea( "Logs" );
this.textArea.setWidth( "100%" );
this.textArea.setReadOnly( true );
this.appendRows( 300 );
Button button = new Button( "Add 10 more rows" , event -> {
this.appendRows( 10 );
} );
this.add( button , this.textArea );
this.setClassName( "main-layout" );
}
private void appendRows ( int countRows ) {
List< String > entries = new ArrayList<>( countRows );
for ( int i = 1 ; i <= countRows ; i++ ) {
entries.add( Instant.now().toString() );
}
Collections.reverse( entries ); // Put newest on top.
String s = entries.stream().collect( Collectors.joining( "\n" ) );
textArea.setValue( s + "\n" + this.textArea.getValue() );
}
}

- 303,325
- 100
- 852
- 1,154
You can put all the text in only one component instead of creating a separate component for each line. If you want line breaks (i.e. \n
) in the text to wrap to the next line, you can adjust the white-space
CSS property for the element to be e.g. pre-line
or pre-wrap
instead. You can do this using component.getElement().getStyle().set("white-space", "pre-wrap")
.
Another alternative if you want to visually indicate the status of the text might be a readonly TextArea
component.
I would also recommend using the Span
component instead of Label
in Vaadin 10. Label
is using the <label>
element in the browser which is actually only intended for labeling input fields, but not for general purpose chucks of text.

- 7,820
- 13
- 19