Skip to content

docs: document the component lifecycle and pin the attribute contract#7656

Open
AKnassa wants to merge 1 commit into
microsoft:mainfrom
AKnassa:docs/7516-lifecycle-guidance
Open

docs: document the component lifecycle and pin the attribute contract#7656
AKnassa wants to merge 1 commit into
microsoft:mainfrom
AKnassa:docs/7516-lifecycle-guidance

Conversation

@AKnassa

@AKnassa AKnassa commented Jul 13, 2026

Copy link
Copy Markdown

What this does

Adds a component lifecycle guide, and turns the surprising parts of element initialization into tests that will fail if the behavior ever changes.

Why

The lifecycle docs were a bare table of callback names with no guidance about how to actually use them. Meanwhile the genuinely surprising parts of initialization were both undocumented and untested:

  • The first oldValue an @attr changed callback receives is undefined, not null. Everyone expects null, because that is what the native attributeChangedCallback gives you. People write if (oldValue !== null) guards against a value that never arrives.
  • A changed callback fires zero, one, or two times during startup, depending on whether the property has a default and whether the attribute is present in markup. Assigning a default in the constructor fires the callback by itself, because the class field initializer goes through the attribute's setter. If the tag also carries the attribute, it fires again.

Nobody had written this down, and nothing pinned it, so it could drift silently.

What changed

00-control-stale-guide-frontmatter 01-sidebar-new-entry 02-sidebar-advanced-closeup 03-content-code-samples 04-console-clean
  • New guide: sites/website/src/docs/3.x/advanced/component-lifecycle.md, linked from the existing lifecycle section.
  • Tests: components/attributes.pw.spec.ts grows from two tests into an executable specification of the initialization contract — the undefined first oldValue, the zero/one/two firing counts, and the ordering of the constructor against connectedCallback.

Two corrections

The issue body contains two claims that are not true, and writing them down would have shipped an authoritative but wrong document. Both are corrected in the guide, and both are now pinned by tests:

  1. "connectedCallback may fire while the constructor is still executing" — it does not. A synchronous constructor body always completes first. The real behaviors worth knowing are that asynchronous work started in a constructor settles after connectedCallback, and that this.isConnected is already true inside the constructor when upgrading an element that is already in the page.
  2. "attributes go null → value" — they go undefined → value.

The guide uses "default value" throughout rather than "initial value", following the terminology already agreed on the issue thread.

Deliberately left open

The issue also raises a design question — should an observed property skip its changed callback on the first run? That is a maintainer's call, and this PR does not decide it.

How to see it

Run the fast-element test suite; the new tests in components/attributes.pw.spec.ts fail if you "correct" the first oldValue to null or change the firing counts. Then preview the docs site: Advanced → Component lifecycle.

Fixes #7516

Adds a component lifecycle guide, and grows the attribute tests into an
executable specification of what actually happens during initialization:
the first oldValue is undefined rather than null, and a changed callback can
fire zero, one or two times depending on defaults and markup.

Fixes microsoft#7516
@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:26
@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.

Add documentation and general guidance around using FASTElement

1 participant