Skip to content

feat: introduce HasComponentsOfType for typed child containers#24186

Merged
mshabarov merged 9 commits intomainfrom
has-components-of-type
May 4, 2026
Merged

feat: introduce HasComponentsOfType for typed child containers#24186
mshabarov merged 9 commits intomainfrom
has-components-of-type

Conversation

@Artur-
Copy link
Copy Markdown
Member

@Artur- Artur- commented Apr 24, 2026

Adds HasComponentsOfType as the typed counterpart of HasComponents, for containers that should only accept a specific child component type (e.g. a breadcrumb trail that only accepts breadcrumb items). HasComponents now extends HasComponentsOfType and keeps the untyped add(String) convenience. All existing default methods are preserved via inheritance.

Adds HasComponentsOfType<T extends Component> as the typed counterpart of
HasComponents, for containers that should only accept a specific child
component type (e.g. a breadcrumb trail that only accepts breadcrumb items).
HasComponents now extends HasComponentsOfType<Component> and keeps the
untyped add(String) convenience. All existing default methods are preserved
via inheritance.
@Artur- Artur- requested a review from mshabarov April 24, 2026 06:43
The childFactory-null error message now references HasComponentsOfType
since that is where the bindChildren default method lives.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 24, 2026

Test Results

 1 395 files  +1   1 395 suites  +1   1h 15m 16s ⏱️ +41s
10 084 tests +3  10 014 ✅ +3  70 💤 ±0  0 ❌ ±0 
10 559 runs  +3  10 480 ✅ +3  79 💤 ±0  0 ❌ ±0 

Results for commit 819bfd8. ± Comparison against base commit dd7e3e6.

♻️ This comment has been updated with latest results.

@Artur-
Copy link
Copy Markdown
Member Author

Artur- commented Apr 24, 2026

There is one compatibility concern with widening the Collection parameters:

Third-party code that does:

class MyLayout extends Component implements HasComponents {                                                                                                              
      @Override                                                                                                                                                            
      public void add(Collection<Component> components) { ... }   // today's signature
}                                                                                                                                                                        

will fail to compile against the new API. Java's override rules require the generic signature to match, not just the erasure. Because Collection and Collection<? extends Component> have the same erasure but different generic signatures, the subclass gets a "method does not override" error AND a "same erasure, different signatures" clash.

It sounds like a rare case but it's not 100% compatible

…ds T

Follows PECS — the Collections passed to add/remove and the factory
passed to bindChildren are producers of T, so wildcards let callers
pass e.g. a List<SubItem> or a factory returning SubItem when the
container type is Item. Binary compatible (same erasure); source-level
this is a breaking change for third-party overrides that pinned the
parameter to Collection<Component> or SerializableFunction<..., Component>,
which must be updated to match the widened signatures.
@github-actions github-actions Bot added +1.0.0 and removed +0.1.0 labels Apr 24, 2026
@mcollovati
Copy link
Copy Markdown
Collaborator

There is one compatibility concern with widening the Collection parameters

Good point. Know that you mentioned it, I remember a similar thing was discussed on another pr recently, but I don't recall the conclusion and what pr was.

I'll try to find it on Monday

@mcollovati
Copy link
Copy Markdown
Collaborator

Probably it was exactly those methods, discussed in an issue. And IIRC the conclusion was that it could be a breaking change for add-ons

@mcollovati
Copy link
Copy Markdown
Collaborator

#23473

It seems it's postponed to Vaadin 26.

Better revert. Sorry for the inconvenience

@github-actions github-actions Bot added +0.1.0 and removed +1.0.0 labels Apr 26, 2026
Copy link
Copy Markdown
Contributor

@mshabarov mshabarov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea looks good to me, though the new API is not fully typed - we hesitate to do full changes because of their breaking nature, thus, we may want to make a second round in Vaadin 26 to close this gap.

We perhaps don't have to immediately apply this interface to our standard components like Tabs, Accordion, and others, where the inner components are always typed, but that's something to consider in the future.

Finally, I can confirm that this change is compatible with the Flow components code base and doesn't trigger compilation errors, but I admit a small risk of unpredicted breaking changes anyway. I believe we can merge this right now, but keep an eye on this topic during alpha and beta testing.

@Artur- Artur- requested a review from mshabarov May 1, 2026 06:47
@mshabarov mshabarov enabled auto-merge May 4, 2026 10:28
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 4, 2026

@mshabarov mshabarov added this pull request to the merge queue May 4, 2026
Merged via the queue into main with commit b9356e4 May 4, 2026
31 checks passed
@mshabarov mshabarov deleted the has-components-of-type branch May 4, 2026 10:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants