Skip to content

docs(core): document resource chaining with chain() in params context#69348

Open
sausi-7 wants to merge 5 commits into
angular:mainfrom
sausi-7:fix/69329-document-resource-chaining
Open

docs(core): document resource chaining with chain() in params context#69348
sausi-7 wants to merge 5 commits into
angular:mainfrom
sausi-7:fix/69329-document-resource-chaining

Conversation

@sausi-7

@sausi-7 sausi-7 commented Jun 14, 2026

Copy link
Copy Markdown

Which issue does this PR close?

Closes #69329

Description

Angular 22 introduced resource chaining via the chain function in ResourceParamsContext. This feature had no documentation in the signals resource guide.

This PR adds a "Chaining resources" section to adev/src/content/guide/signals/resource.md covering:

  • Basic usage of chain(resource) inside params to make one resource depend on another
  • Automatic status propagation — when the upstream is loading / idle / error, the downstream mirrors that status so the loader never runs with missing data
  • Chaining vs reading .value() directly — explains why chain is preferred: reading .value() collapses any non-resolved state to idle, whereas chain correctly propagates loading and error
  • Synchronous value transformation — covers the common pattern of mapping a resource's value synchronously and notes when computed is a better fit

Type of change

  • Documentation content changes

Checklist

Adds a new 'Chaining resources' section to the resource guide covering:
- Basic usage of chain() to depend one resource on another
- Automatic status propagation (loading/idle/error)
- Chaining vs reading .value() directly
- Synchronous value transformation via chained resource

Closes angular#69329
@pullapprove pullapprove Bot requested a review from MarkTechson June 14, 2026 17:41
@google-cla

google-cla Bot commented Jun 14, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@angular-robot angular-robot Bot added area: docs Related to the documentation area: core Issues related to the framework runtime labels Jun 14, 2026
@ngbot ngbot Bot added this to the Backlog milestone Jun 14, 2026
@sausi-7

sausi-7 commented Jun 14, 2026

Copy link
Copy Markdown
Author

I have signed the CLA.

Comment thread adev/src/content/guide/signals/resource.md
Comment thread adev/src/content/guide/signals/resource.md Outdated
Pass the chained value directly as params so when chain() returns
undefined the downstream resource becomes idle rather than throwing.

Addresses review feedback from @JeanMeche on PR angular#69348.
@sausi-7

sausi-7 commented Jun 14, 2026

Copy link
Copy Markdown
Author

Good catch, thank you! Updated the example to pass the chained value directly as params (chain(userResource)?.id) so when chain() returns undefined the downstream resource correctly becomes idle rather than attempting to access .id on undefined. Also added a note explaining this behaviour.

The example used an async resource to do synchronous string mapping then
recommended computed instead, which was confusing. Replaced with a concise
note clarifying when to reach for chain vs computed.

Addresses review feedback from @JeanMeche on PR angular#69348.
@sausi-7

sausi-7 commented Jun 14, 2026

Copy link
Copy Markdown
Author

You're right, that section was misleading. It used an async resource to do synchronous string mapping and then said to use computed instead, so it was basically showing an anti pattern as if it was a feature. I removed it and added a short note instead clarifying that chain is for when the downstream resource does its own async work, and computed is the right tool when you just need to derive a value synchronously.

Comment thread adev/src/content/guide/signals/resource.md Outdated
Reword the description so it matches chain(userResource)?.id being passed
directly as params, and explain why returning the value directly (instead
of wrapping it in an object) keeps the idle behaviour.

Addresses review feedback from @JeanMeche on PR angular#69348.
@sausi-7

sausi-7 commented Jun 14, 2026

Copy link
Copy Markdown
Author

Updated the wording so it matches the new example. It now says chain reads the value (which can be undefined) instead of saying it returns the resolved value, and the bullet for the resolved case reflects that the value is used as params. I also rephrased the note to explain why passing chain(userResource)?.id directly matters: if you wrap it in an object like {userId: undefined} the params are still defined so the loader would run with an undefined id, whereas passing the value directly lets the resource go idle when there is no upstream value.

- If `userResource` is in an **error** state, `userPostsResource` also enters the `error` state.
- If `userResource` is **resolved**, `chain` returns its value, which `userPostsResource` then uses as its params.

A resource's value can be `undefined`, so `chain` can return `undefined` too. The example passes `chain(userResource)?.id` directly as the params value, so when there is no upstream value the params are `undefined` and `userPostsResource` becomes `idle`. Returning the value directly is important here: a params value like `{userId: undefined}` is still defined, so it would run the loader with an `undefined` id instead.

@JeanMeche JeanMeche Jun 14, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that sentence makes a lot of sense.

A resource's value can be undefined, so chain can return undefined too.
This is indeed true but I'm not sure this is worth calling out.

The example passes chain(userResource)?.id directly as the params value, so when there is no upstream value the params are undefined and userPostsResource becomes idle.

But if a resource is idle or loading, chain() will actually throw a specific error do the loader won't run because of the said error.

Returning the value directly is important here: a params value like {userId: undefined} is still defined, so it would run the loader with an undefined id instead.

This might be worth a callout on its own with NOTE:

@JeanMeche JeanMeche requested review from JeanMeche and removed request for MarkTechson June 14, 2026 20:01
…to callout

Clarify that chain throws to propagate status when the upstream resource is
not resolved, and only returns undefined when the resolved value is undefined.
Move the direct-value vs object params guidance into its own NOTE callout.

Addresses review feedback from @JeanMeche on PR angular#69348.
@sausi-7

sausi-7 commented Jun 15, 2026

Copy link
Copy Markdown
Author

Both good points, fixed. You're right that chain throws when the resource is idle or loading, it does not return undefined in those cases. I reworded it so it now says chain throws to propagate the status when the upstream is not resolved, and that it only returns undefined when the resolved value itself is undefined. I also moved the bit about passing the value directly instead of wrapping it in an object into its own NOTE callout.

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

Labels

area: core Issues related to the framework runtime area: docs Related to the documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document resource chaining

2 participants