Perform action after page load - Detect view rendered

I need to delay a method call, until the entire view is rendered in the client. What is the best approach to use or is there an event / method available? - From what I have read up on, there is no ‘onload’ or ‘complete’ event available.

I have also tried the ‘enter’ method and the navigator ‘afterViewChange’, however both are called before the page is rendered.

Same Problem…
But this was 6 years ago so are there any solutions?

maybe try using the Component::onAttach method. I believe this should execute at that time.

@Route("test")
public class TestView extends VerticalLayout {
	public TestView(){
		// variant 1: add an attachListener to a component instance
		addAttachListener(attachEvent -> {
			// view is loaded at this point. You can for example execute javascript which relies on certain elements being in the page
		});
	}
	
	// variant 2: override onAttach method of the component class
	@Override
    public void onAttach(AttachEvent event){
        // view is loaded at this point. You can for example execute javascript which relies on certain elements being in the page
    }
}

Thanks, this was very helpful. I have found another workaround, but this works as well!

Purely out of interest, what is the other workaround that you have found?

I wait until the “v-loading-indicator first” has “display:none” in his style attribute. This means that the page has loaded completely. Its not a very clever workaround since there is no event for it. So I had to make a loop that checks several times if display = none. Therefore I think the onAttach is the better solution.

Hi guys, I just wanted to provide the workaround that Philipp mentioned because it took me some time to get it to work on my side, and I’m sure the next person coming will love to copy/paste it :slight_smile:

PendingJavaScriptResult loadingFinished = UI.getCurrent().getPage().executeJs(""
				+ "function delay() {\n"
				+ "  return new Promise(function(resolve) { \n"
				+ "    setTimeout(resolve, 50)\n"
				+ "  });\n"
				+ "}\n"
				+ "async function waitForLoadingToFinish() {\n"
				+ "  while(true) {\n"
				+ "    let progressElement = document.getElementsByClassName('v-loading-indicator');\n"
				+ "    if (progressElement[0]
.style.display == 'none') {\n"
				+ "      return true;\n"
				+ "    } else {\n"
				+ "      await delay();\n"
				+ "    }\n"
				+ "  }\n"
				+ "}\n"
				+ "return waitForLoadingToFinish();");

loadingFinished.then(Boolean.class, (res) -> {
	// do something
});

I couldn’t use the onAttach() solution because of some other reasons and I do believe that Vaadin could provide an easy “event listener” approach for the ‘v-loading-indicator’ because it could also be used in other cases.

Vincent Bonnefoy:
Hi guys, I just wanted to provide the workaround that Philipp mentioned because it took me some time to get it to work on my side, and I’m sure the next person coming will love to copy/paste it :slight_smile:

PendingJavaScriptResult loadingFinished = UI.getCurrent().getPage().executeJs(""
				+ "function delay() {\n"
				+ "  return new Promise(function(resolve) { \n"
				+ "    setTimeout(resolve, 50)\n"
				+ "  });\n"
				+ "}\n"
				+ "async function waitForLoadingToFinish() {\n"
				+ "  while(true) {\n"
				+ "    let progressElement = document.getElementsByClassName('v-loading-indicator');\n"
				+ "    if (progressElement[0]

.style.display == ‘none’) {\n"

  		+ "      return true;\n"
  		+ "    } else {\n"
  		+ "      await delay();\n"
  		+ "    }\n"
  		+ "  }\n"
  		+ "}\n"
  		+ "return waitForLoadingToFinish();");

loadingFinished.then(Boolean.class, (res) → {
// do something
});


I couldn't use the onAttach() solution because of some other reasons and I do believe that Vaadin could provide an easy "event listener" approach for the 'v-loading-indicator' because it could also be used in other cases.

This solution works only with Vaadin Flow.