Implement (element) helper for dynamic tag names (RFC #0389)#21230
Open
NullVoxPopuli-ai-agent wants to merge 3 commits intoemberjs:mainfrom
Open
Implement (element) helper for dynamic tag names (RFC #0389)#21230NullVoxPopuli-ai-agent wants to merge 3 commits intoemberjs:mainfrom
(element) helper for dynamic tag names (RFC #0389)#21230NullVoxPopuli-ai-agent wants to merge 3 commits intoemberjs:mainfrom
Conversation
Implements the `element` helper as specified in RFC emberjs#389, allowing dynamic tag names in Glimmer templates. The helper returns a component definition that renders the specified HTML element around yielded content. Behavior: - `(element "h1")` renders an `<h1>` wrapping the block content - `(element "")` renders block content without a wrapping element - `(element null)` / `(element undefined)` renders nothing - Invalid types (number, boolean, object) throw in development mode - Tag name changes trigger teardown/recreation of the element Available in both loose mode (built-in) and strict mode (importable from `@ember/helper`). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/@ember/-internals/glimmer/tests/integration/helpers/element-test.js
Show resolved
Hide resolved
NullVoxPopuli
previously approved these changes
Mar 26, 2026
Contributor
|
Tested on the big app at work, and aside from ember not owning the |
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the
elementhelper as specified in RFC #0389, continuing the work started in #21048.(element "h1")— renders an<h1>wrapping the block content, with full support for attributes, modifiers, and...attributes(element "")— renders block content without a wrapping element(element null)/(element undefined)— renders nothing (<!---->)The helper is available in both loose mode (as a built-in helper) and strict mode (importable from
@ember/helper).Implementation approach
Uses the Glimmer VM's
WrappedBuilderwithdynamicTag: trueandwrapped: truecapabilities. Theelementhelper returns a lightweight component definition per tag name:ElementComponentDefinitionwith a customElementComponentManagerthat provides the tag name viagetTagName(). The VM's default template ({{yield}}) is used viaasWrappedLayout(), which wraps it with dynamic element open/close opcodes.getTagName()returnsnull, so theWrappedBuilderskips the element and just yields the block.VoidElementComponentDefinitionwith an empty template (no yield), so nothing is rendered.Files changed
packages/@ember/-internals/glimmer/lib/helpers/element.ts— Core implementationpackages/@ember/-internals/glimmer/lib/resolver.ts— Registered inBUILTIN_HELPERSfor loose modepackages/@ember/-internals/glimmer/index.ts— Re-exportpackages/@ember/helper/index.ts— Public export for strict modepackages/@ember/-internals/glimmer/tests/integration/helpers/element-test.js— 15 testsTest plan
defineComponentwith importedelementnullandundefinedrender nothing (<!---->){{on "click" ...}}) work on the dynamic element@tagargument with...attributes🤖 Generated with Claude Code