Skip to content

feat: add a single option to slotted and children#7652

Open
AKnassa wants to merge 1 commit into
microsoft:mainfrom
AKnassa:feat/5450-slotted-single-node
Open

feat: add a single option to slotted and children#7652
AKnassa wants to merge 1 commit into
microsoft:mainfrom
AKnassa:feat/5450-slotted-single-node

Conversation

@AKnassa

@AKnassa AKnassa commented Jul 13, 2026

Copy link
Copy Markdown

What this does

Lets slotted and children hand you a single element instead of always handing you an array.

Why

ref gives you the node directly. slotted and children always give you an array — even when you have filtered down to the one element you actually want. So every use site ends up writing this.thing[0] and guarding for emptiness by hand.

In the original report, someone building a wrapper with two named slots ended up reaching into this.$fastController.view.behaviors[0].target.assignedNodes[0] to get at a single node. That was fairly described at the time as "pretty brittle code."

What changed

  • slotted and children accept single: true.
  • With it, the property is assigned the first matching node, or null when nothing matches — the same shape ref gives you.
  • Both directives get this from one shared code path, so children gets it automatically.
  • The declarative syntax and the template generator round-trip the option, so it works in declarative templates too.
@slotted({ property: "header", filter: elements("h1"), single: true })
header!: HTMLElement | null;

How to see it

Run the fast-element test suite. templating/slotted.pw.spec.ts and templating/children.pw.spec.ts cover the single-node case: the first match is assigned directly, null when the slot is empty or the filter matches nothing, and it updates on slotchange.

One behavior worth calling out, because it is genuinely new: observables compare with !==, so with single the property does not re-notify when the first match happens to be unchanged across a slot change. That is asserted in the tests.

Two things for reviewers

Naming. single was chosen over first or multiple: false because it reads as a description of the result, not of the traversal. Happy to change it.

One extra change, deliberately. packages/fast-test-harness reconstructs these directives when generating declarative templates, so it had to learn the new option or the fixtures would silently lose it. While there, it was also fabricating a filter elements() for any filter it could not represent — quietly narrowing what you observe to elements only. It now emits no filter and warns instead, so an unrepresentable filter degrades loudly rather than silently changing behavior.

Fixes #5450

Both directives always assigned an array, so a slot holding one element still
forced consumers to index into it and guard for emptiness at every use site.

Passing `single: true` now assigns the first matching node directly, or null
when nothing matches, mirroring how `ref` behaves. The declarative syntax and
the template generator round-trip the option.

Fixes microsoft#5450
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@AKnassa AKnassa marked this pull request as ready for review July 14, 2026 02:28
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add ability to return only one element from SlottedBehavior

1 participant