Just wondering, is there any life-cycle method we can override in CustomComponent to do the actual component layout / construction?
Currently I’m using each CustomComponent’s constructor for the layout logic, and pass in any required data as constructor parameters.
However, this gets a little unwieldly when there are a large number of parameters to pass in, and also when 2 components need to reference each other during ‘construction’.
What do you mean by “life-cycle methods”?
Do you mean a hand-written CustomComponent or one created with the Visual Editor?
For components created with the Visual Editor, the server-side part of the layout construction is performed in the constructor, you can write your own code after that. Methods and fields tagged with @AutoGenerated should not be edited by hand, they are parsed by the Visual Editor and can be modified/deleted by the Visual Editor.
You could override the attach() method if you want to hook some code to the time the component is added to a layout. That way, you could set some field values with constructor parameters or setters and then use them in attach().
I mean something like an init() method that’s called by the framework, inside which we can place our layout / construction logic. And I’m referring to hand-written CustomComponent.
If there’s such a method, then we can do additional component configuration after the constructor call, rather than having to pass all required data to the constructor.
Looks like this could be the one.
I have many CustomComponents nested inside other CustomComponents. So can I move all the code from their constructors to their respective attach(), including the calls to setCompositionRoot(…)? eg. it’ll look like this:
@Override
public void attach() {
super.attach();
setSizeFull();
VerticalLayout panelRoot = new VerticalLayout();
// ... then create and add other nested CustomCompnents
setCompositionRoot(panelRoot);
}
Would it break anything or cause infinite loops? (super.attach() in CustomComponent seems to call attach() on all its child components, which aren’t there until the end of the overriden attach() …)
You must set the composition root in the constructor, or at least before attach() is called. Well, you can re-set it again later, for example in the attach().
The child components are attached when calling setCompositionRoot() and addComponent(), so you don’t need to worry about that.
You must set the composition root in the constructor, or at least before attach() is called.
...
The child components are attached when calling setCompositionRoot() and addComponent()
Hmm, need to think about this a bit more then … would if work all the layout code is in attach(), including setCompositionRoot(…), then I call super.attach() right at the end instead of the start? eg:
@Override
public void attach() {
VerticalLayout panelRoot = new VerticalLayout();
// ... additional layout logic with more nested CustomComponents added to panelRoot
setCompositionRoot(panelRoot);
super.attach();
}
The reason I move setCompositionRoot(…) from the constructor into attach() is that the root might depend on additional configurations done after the constructor call.
Say the above is the top-most component, which is set as the main window’s content. Would it work? (seems to, just running through it in my head, though if I understand correctly, each child’s attach() will be called multiple times …)
I don’t think it matters in which order you create the child components and when you call the super.attach(). You can call it in the beginning. Attach is called only once for each component.
Doing initializations in attach() is rarely absolutely necessary. Sometimes it is. It has some benefits, such as always having access to the application and window objects without having to pass them as parameters for the constructor. This makes internationalization easier at least. The disadvantage is that it adds a bit complexity and extra code to every CustomComponent (such as setting a temporary composition root in the constructor).
The documentation of CustomComponent constructor states that the composition root has to be set before the component is used.
In the current Vaadin version it needs to be set before painting the CustomComponent or iterating over its contents. If there is no code that explicitly checks the contained component count or iterates over subcomponents, you can probably set the root in attach().
Nevertheless, for future-proofing your application, I would suggest you set e.g. an empty CssLayout as the composition root in your constructor and then change it in attach().