Skip to content

feat(fast-html): add |binding:none non-reactive static accessor syntax#7374

Draft
janechu wants to merge 3 commits intomainfrom
users/janechu/add-non-binding
Draft

feat(fast-html): add |binding:none non-reactive static accessor syntax#7374
janechu wants to merge 3 commits intomainfrom
users/janechu/add-non-binding

Conversation

@janechu
Copy link
Copy Markdown
Collaborator

@janechu janechu commented Apr 3, 2026

Summary

Adds support for {{foo|binding:none}} syntax in @microsoft/fast-html templates. This creates a one-time (non-reactive) static accessor instead of a reactive binding.

Motivation

All current {{}} bindings are reactive — they set up observers so the DOM updates whenever the bound property changes. This PR adds a way to opt out of reactivity for cases where a value only needs to be read once on element connect.

Changes

packages/fast-html

  • src/components/syntax.ts: Add noneBindingModifier = "|binding:none" constant
  • src/components/utilities.ts: Add hasNoneBindingModifier and stripNoneBindingModifier helper functions
  • src/components/template.ts: Import oneTime from @microsoft/fast-element; detect |binding:none modifier in content bindings and use oneTime() instead of a reactive function
  • test/fixtures/static-accessor/: New test fixture verifying non-reactive rendering
  • README.md: Document the new Static accessor syntax

Behavior

Syntax Equivalent Reactive?
{{text}} ${x => x.text} ✅ Yes
`{{text binding:none}}` ${x.text} (one-time)

Test

New test in test/fixtures/static-accessor/static-accessor.spec.ts verifies:

  1. The initial value is rendered correctly
  2. After changing the attribute, the DOM content does not update (no reactivity)

janechu and others added 3 commits April 3, 2026 13:02
Add support for {{foo|binding:none}} which creates a one-time (non-reactive)
accessor instead of a reactive binding. This means the value is read once when
the element connects and the DOM is not updated when the property changes.

Changes:
- Add noneBindingModifier to syntax.ts
- Add hasNoneBindingModifier and stripNoneBindingModifier helpers in utilities.ts
- Import oneTime from @microsoft/fast-element in template.ts
- Use oneTime binding when |binding:none modifier is detected in content bindings
- Add test fixtures in packages/fast-html/test/fixtures/static-accessor
- Update README.md with Static accessor section
- Apply biome formatting fixes across the package

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ntax

Replace the single-purpose noneBindingModifier with a general pipe-based
argument parsing system for declarative binding expressions.

Syntax: {{path|key1:value1|key2:value2}}
- The first segment (before any |) is always the property path
- Each subsequent segment is split on : into a key/value modifier pair

Changes:
- syntax.ts: replace noneBindingModifier with bindingArgSeparator (|),
  bindingArgKeyValueSeparator (:), bindingKey, and noneBinding constants
- utilities.ts: replace hasNoneBindingModifier/stripNoneBindingModifier with
  parseBindingExpression() returning { path, modifiers }
- template.ts: use parseBindingExpression and check modifiers[bindingKey]
  === noneBinding to detect one-time accessor intent

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a 'Binding arguments' section under Syntax explaining the general
pipe-separator format: {{path|key1:value1|key2:value2}}

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

1 participant