feat: propagate <f-template> host attributes onto rendered host element#7521
Conversation
Static, {{expr}}, and ?name="{{expr}}" attributes declared on the inner
<template> of an <f-template> now propagate onto the rendered host
element opening tag during SSR. Author-provided host attributes win on
conflict. Client-only attribute prefixes (@, :, f-ref, f-slotted,
f-children) are skipped.
* locator.rs: extract_template_content returns (content, host_attrs);
add_template_with_attrs(name, content, shadowroot_attrs, host_attrs)
replaces the prior shadowroot-only helper (breaking change in
prerelease).
* directive.rs: render_custom_element splices template host attrs into
the host opening tag for both entry and nested paths.
* wasm.rs / packages/fast-build/bin/fast.js: hostAttributes flow
through templatesMap and parse_f_templates JSON.
* Adds host-autofocus fixture component and Playwright assertion.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… fixture Biome's HTML formatter collapses <template> elements with short content onto a single line, which causes the WASM SSR renderer in @microsoft/fast-build to drop the leading fe-b$$start binding marker for the first-position text node inside the host element. Without the start marker, client hydration cannot bound the binding range and clears the rendered content. Restore the original multi-line <template> layout in templates.html and add biome-ignore-all comments at the top of templates.html and entry.html so future biome:fix runs preserve the layout. Index.html is regenerated from the restored sources. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
This doesn't make sense why we want this magic: to propagate to: Why do we want component devs to propagate attributes? This doesn't follow the w3c spec, if they want So I am not fan doing this approach. |
Commented in the other implementation, this is basically our current method on CSR (Client Side Rendering), we take static attributes from the The specific use case in which it is very awkward on the platform is use of Component authors can choose not to use it, but since it is already an aspect of |
…ge (#7522) # Pull Request ## 📖 Description Adds a new **"Host Attribute Propagation"** section to the 3.x declarative server-rendering documentation page (`sites/website/src/docs/3.x/declarative-templates/server-rendering.md`) describing how attributes declared on the inner `<template>` of an `<f-template>` propagate onto the rendered host element opening tag during SSR. The new section covers: - The concept and a worked example (a `primary-button` component with `tabindex`, `role`, and `class` declared on its template). - The three supported binding forms: static `name="value"`, dynamic `name="{{expression}}"`, and boolean `?name="{{expression}}"`, including which values get stripped. - The client-only attribute skip list (`@event`, `:property`, `f-ref`, `f-slotted`, `f-children`). - The "author wins on conflict" dedupe rule (including how `?name` dedupes against the bare `name`). ### 🎫 Issues This documents the build-time renderer behavior implemented on `main` in [#7521](#7521). The feature will be picked up by the next `main` → `releases/fast-element-v3` sync; this docs PR can land independently so that the website reflects the upcoming behavior. ## 👩💻 Reviewer Notes - Docs-only change — no source, test, or build configuration is touched. - The new section is placed between **State Propagation** and **Using `@microsoft/fast-build`**, keeping the conceptual flow (rendering contract → hydration flow → state in → host attrs out → tooling). - Markdown is wrapped inside the existing `{% raw %}` Nunjucks block so that `{{ }}` examples render literally on the site. ## 📑 Test Plan - No test changes are required. Verified the markdown edits render correctly by inspection (no broken table syntax, no unescaped Nunjucks/Liquid braces outside `{% raw %}`). - Suggested smoke test for reviewer: `npm run build -w @microsoft/fast-site` (or the website's local dev preview) and open the rendered `server-rendering` page to confirm the new section displays as expected. ## ✅ Checklist ### General - [ ] I have included a change request file using `$ npm run change` - [ ] I have added tests for my changes. - [ ] I have tested my changes. - [x] I have updated the project documentation to reflect my changes. - [x] I have read the [CONTRIBUTING](https://github.com/microsoft/fast/blob/main/CONTRIBUTING.md) documentation and followed the [standards](https://github.com/microsoft/fast/blob/main/CODE_OF_CONDUCT.md#our-standards) for this project. ## ⏭ Next Steps When the next `main` → `releases/fast-element-v3` sync lands, this docs page will accurately describe the behavior shipping in the v3 build pipeline. No further docs work is anticipated for this feature on the v3 track.
Pull Request
📖 Description
Adds support for propagating host attributes declared on the inner
<template>of an<f-template>definition onto the rendered host element opening tag during SSR.Today the build-time renderer drops every attribute on the source
<template>, so authors cannot pre-declare host attributes (e.g.tabindex,role,aria-*) on a component's declarative template. After this change, the following template:Now renders as
<host-autofocus autofocus tabindex="0">…</host-autofocus>when the author writes<host-autofocus autofocus></host-autofocus>— both the author-providedautofocusand the template-providedtabindex="0"survive SSR.Resolution rules:
name="value", dynamicname="{{expr}}", and boolean?name="{{expr}}"bindings on the template's<template>are propagated.?namededupes against barename).@event,:property,f-ref,f-slotted,f-children.{{expr}}resolves against the same state used to render the shadow root; non-primitive / null values are stripped.Breaking change (prerelease):
Locator::add_template_with_shadowroot_attrswas renamed and widened toadd_template_with_attrs(name, content, shadowroot_attrs, host_attrs).Locator::from_template_definitionsis nowpuband accepts a 3-tuple metadata value(content, shadowroot_attrs, host_attrs). The WASM/JSON shapetemplatesMap[name]now includes ahostAttributesarray. No external callers existed inside the monorepo.👩💻 Reviewer Notes
crates/microsoft-fast-build/src/directive.rsis where the actual splice happens.merge_template_host_attrsformats and joins filtered attrs before the rightmost>of the host opening tag.fast-html); see theis_client_only_attrhelper for the canonical list.packages/fast-html/test/fixtures/host-bindings) gained an intentionalautofocususage; abiome-ignore lint/a11y/noAutofocusHTML comment documents the rationale and survivesnpm run build:fixturesregeneration ofindex.html.📑 Test Plan
crates/microsoft-fast-build(tests/host_attributes.rs+locator.rsunit tests + 2 WASM tests) — all 87 cargo tests pass.packages/fast-html/test/fixtures/host-bindings/host-bindings.spec.tsverifying bothautofocus(author) andtabindex="0"(propagated) survive SSR + hydration.npm run build✓,npm run test✓ (301/301 fast-html chromium, no regressions in other fixtures),npm run biome:check✓,npm run checkchange✓.✅ Checklist
General
$ npm run change