-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Angular v19+ pending tasks and lazy derived signal proxy initialization #9986
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…nput signal too soon
…nal based adapters
🦋 Changeset detectedLatest commit: 00ba5b4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughUpdates Angular Query experimental package to require Angular v19+, integrates Angular's native PendingTasks API, refactors tests to component-based patterns with OnPush change detection, excludes certain observer methods from signal proxies, and updates documentation examples and compatibility notes. Changes
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Rationale: Large, heterogeneous refactor spanning 40+ files with multiple distinct change patterns: (1) comprehensive API signature updates affecting all public query/mutation/options types and signalProxy, (2) dense logic changes in create-base-query and types leveraging PendingTasks, LinkedSignal, and computed patterns, (3) extensive test infrastructure rewrite affecting 16 test files with new component-based patterns and OnPush change detection, (4) distributed documentation updates across 25+ guides requiring cross-file reasoning on example consistency. Mix of conceptual changes (pending task lifecycle, method exclusion) and implementation details (TestBed setup consolidation, signal access patterns) demands careful review of type safety, backward compatibility, and testing coverage alignment. Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Changed back |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (5)
.changeset/deep-crews-open.md (1)
5-5: Consider expanding the changeset message for clarity.The message is brief. Consider adding more detail about the key changes (e.g., signal proxy improvements, PendingTasks integration, or removal of Angular <19 compatibility) to help consumers understand the scope of the update.
packages/angular-query-experimental/src/__tests__/with-devtools.test.ts (1)
138-138: LGTM! Consistent test utility usage.Replacing direct timer advancement with
flushQueryUpdates()provides better abstraction and makes the test suite more maintainable. This utility wraps the timer advancement logic in a semantic function name that clearly communicates intent.Also applies to: 170-170, 190-190, 206-206, 251-251, 291-291, 323-323, 354-354, 387-387, 417-417, 443-443, 473-473, 530-530, 551-551, 581-581
packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts (1)
39-41: LGTM! Cleaner test setup.Using
setupTanStackQueryTestBedconsolidates common TestBed configuration while allowing test-specific providers (ElementRef) to be added cleanly. This improves maintainability and reduces duplication across the test suite.docs/framework/angular/quick-start.md (1)
38-38: Minor inconsistency in provider ordering between examples.The NgModule example has
provideTanStackQuerybeforeprovideHttpClient, while thebootstrapApplicationexample on line 22 has the opposite order. Consider aligning the order for consistency across examples.🔎 Suggested fix
- providers: [provideTanStackQuery(new QueryClient()), provideHttpClient()], + providers: [provideHttpClient(), provideTanStackQuery(new QueryClient())],packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts (1)
540-588: Consider extracting TestBed reset pattern.Multiple tests repeat the
TestBed.resetTestingModule()+TestBed.configureTestingModule()pattern with identical providers. Consider using thesetupTanStackQueryTestBedutility fromtest-utils.tsto reduce duplication.🔎 Proposed refactor
test('should handle synchronous mutation with retry', async () => { - TestBed.resetTestingModule() - TestBed.configureTestingModule({ - providers: [ - provideZonelessChangeDetection(), - provideTanStackQuery(queryClient), - ], - }) + setupTanStackQueryTestBed(queryClient) const app = TestBed.inject(ApplicationRef)Apply similar changes to other tests that reset the TestBed.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (57)
.changeset/deep-crews-open.mddocs/framework/angular/angular-httpclient-and-other-data-fetching-clients.mddocs/framework/angular/guides/caching.mddocs/framework/angular/guides/default-query-function.mddocs/framework/angular/guides/dependent-queries.mddocs/framework/angular/guides/disabling-queries.mddocs/framework/angular/guides/does-this-replace-client-state.mddocs/framework/angular/guides/important-defaults.mddocs/framework/angular/guides/infinite-queries.mddocs/framework/angular/guides/initial-query-data.mddocs/framework/angular/guides/invalidations-from-mutations.mddocs/framework/angular/guides/mutations.mddocs/framework/angular/guides/paginated-queries.mddocs/framework/angular/guides/parallel-queries.mddocs/framework/angular/guides/placeholder-query-data.mddocs/framework/angular/guides/queries.mddocs/framework/angular/guides/query-functions.mddocs/framework/angular/guides/query-invalidation.mddocs/framework/angular/guides/query-options.mddocs/framework/angular/guides/query-retries.mddocs/framework/angular/guides/testing.mddocs/framework/angular/installation.mddocs/framework/angular/overview.mddocs/framework/angular/quick-start.mddocs/framework/angular/reference/functions/injectQuery.mddocs/framework/angular/typescript.mdexamples/angular/infinite-query-with-max-pages/src/app/components/example.component.tsexamples/angular/optimistic-updates/src/app/components/optimistic-updates.component.tspackages/angular-query-experimental/README.mdpackages/angular-query-experimental/package.jsonpackages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.tspackages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.tspackages/angular-query-experimental/src/__tests__/inject-infinite-query.test.tspackages/angular-query-experimental/src/__tests__/inject-is-fetching.test.tspackages/angular-query-experimental/src/__tests__/inject-is-mutating.test.tspackages/angular-query-experimental/src/__tests__/inject-mutation-state.test.tspackages/angular-query-experimental/src/__tests__/inject-mutation.test.tspackages/angular-query-experimental/src/__tests__/inject-queries.test-d.tspackages/angular-query-experimental/src/__tests__/inject-queries.test.tspackages/angular-query-experimental/src/__tests__/inject-query.test-d.tspackages/angular-query-experimental/src/__tests__/inject-query.test.tspackages/angular-query-experimental/src/__tests__/mutation-options.test.tspackages/angular-query-experimental/src/__tests__/pending-tasks-ssr.test.tspackages/angular-query-experimental/src/__tests__/pending-tasks.test.tspackages/angular-query-experimental/src/__tests__/signal-proxy.test.tspackages/angular-query-experimental/src/__tests__/test-utils.tspackages/angular-query-experimental/src/__tests__/with-devtools.test.tspackages/angular-query-experimental/src/create-base-query.tspackages/angular-query-experimental/src/inject-infinite-query.tspackages/angular-query-experimental/src/inject-mutation.tspackages/angular-query-experimental/src/inject-queries.tspackages/angular-query-experimental/src/inject-query.tspackages/angular-query-experimental/src/pending-tasks-compat.tspackages/angular-query-experimental/src/query-options.tspackages/angular-query-experimental/src/signal-proxy.tspackages/angular-query-experimental/src/types.tspackages/angular-query-persist-client/package.json
💤 Files with no reviewable changes (4)
- docs/framework/angular/guides/important-defaults.md
- docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md
- packages/angular-query-persist-client/package.json
- packages/angular-query-experimental/src/pending-tasks-compat.ts
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: arnoud-dv
Repo: TanStack/query PR: 9669
File: docs/framework/angular/guides/testing.md:49-56
Timestamp: 2025-09-21T00:31:02.518Z
Learning: TestBed.tick() is a valid API introduced in Angular 20 for triggering effects in unit tests, similar to ApplicationRef.tick() but for testing contexts.
📚 Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.
Applied to files:
packages/angular-query-experimental/src/__tests__/pending-tasks-ssr.test.tspackages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.tspackages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.tspackages/angular-query-experimental/src/__tests__/test-utils.tspackages/angular-query-experimental/src/__tests__/inject-query.test-d.tsdocs/framework/angular/reference/functions/injectQuery.mdpackages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts.changeset/deep-crews-open.mddocs/framework/angular/guides/query-functions.mdpackages/angular-query-experimental/src/__tests__/with-devtools.test.tsdocs/framework/angular/typescript.mddocs/framework/angular/overview.mdpackages/angular-query-experimental/src/__tests__/inject-mutation.test.tsdocs/framework/angular/guides/query-invalidation.mddocs/framework/angular/guides/query-retries.mddocs/framework/angular/guides/testing.mdpackages/angular-query-experimental/src/__tests__/inject-is-fetching.test.tspackages/angular-query-experimental/src/__tests__/inject-is-mutating.test.tspackages/angular-query-experimental/src/inject-mutation.tspackages/angular-query-experimental/src/__tests__/mutation-options.test.tspackages/angular-query-experimental/src/create-base-query.tsdocs/framework/angular/guides/disabling-queries.mddocs/framework/angular/guides/initial-query-data.mdpackages/angular-query-experimental/src/__tests__/inject-query.test.tspackages/angular-query-experimental/src/__tests__/inject-mutation-state.test.tspackages/angular-query-experimental/src/__tests__/inject-queries.test.tspackages/angular-query-experimental/src/__tests__/inject-infinite-query.test.tspackages/angular-query-experimental/src/__tests__/pending-tasks.test.tsdocs/framework/angular/guides/dependent-queries.mdpackages/angular-query-experimental/src/query-options.tsdocs/framework/angular/guides/parallel-queries.md
📚 Learning: 2025-09-21T00:31:02.518Z
Learnt from: arnoud-dv
Repo: TanStack/query PR: 9669
File: docs/framework/angular/guides/testing.md:49-56
Timestamp: 2025-09-21T00:31:02.518Z
Learning: TestBed.tick() is a valid API introduced in Angular 20 for triggering effects in unit tests, similar to ApplicationRef.tick() but for testing contexts.
Applied to files:
packages/angular-query-experimental/src/__tests__/pending-tasks-ssr.test.tspackages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.tspackages/angular-query-experimental/src/__tests__/test-utils.ts.changeset/deep-crews-open.mdpackages/angular-query-experimental/src/__tests__/with-devtools.test.tspackages/angular-query-experimental/src/__tests__/signal-proxy.test.tspackages/angular-query-experimental/src/__tests__/inject-mutation.test.tsdocs/framework/angular/guides/testing.mdpackages/angular-query-experimental/src/__tests__/inject-is-fetching.test.tspackages/angular-query-experimental/src/__tests__/inject-is-mutating.test.tspackages/angular-query-experimental/src/__tests__/mutation-options.test.tspackages/angular-query-experimental/src/__tests__/inject-query.test.tspackages/angular-query-experimental/src/__tests__/inject-mutation-state.test.tspackages/angular-query-experimental/src/__tests__/inject-queries.test.tspackages/angular-query-experimental/src/__tests__/inject-infinite-query.test.tspackages/angular-query-experimental/src/__tests__/pending-tasks.test.ts
📚 Learning: 2025-11-02T22:52:33.071Z
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.
Applied to files:
packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.tspackages/angular-query-experimental/src/__tests__/inject-query.test-d.tsdocs/framework/angular/guides/query-functions.mddocs/framework/angular/overview.mddocs/framework/angular/guides/query-retries.mdpackages/angular-query-experimental/src/inject-infinite-query.tspackages/angular-query-experimental/src/inject-queries.tsdocs/framework/angular/guides/disabling-queries.mdpackages/angular-query-experimental/src/__tests__/inject-query.test.tspackages/angular-query-experimental/src/inject-query.tspackages/angular-query-experimental/src/query-options.tspackages/angular-query-experimental/src/types.tsdocs/framework/angular/guides/query-options.md
📚 Learning: 2025-09-02T17:57:33.184Z
Learnt from: TkDodo
Repo: TanStack/query PR: 9612
File: packages/query-async-storage-persister/src/asyncThrottle.ts:0-0
Timestamp: 2025-09-02T17:57:33.184Z
Learning: When importing from tanstack/query-core in other TanStack Query packages like query-async-storage-persister, a workspace dependency "tanstack/query-core": "workspace:*" needs to be added to the package.json.
Applied to files:
packages/angular-query-experimental/package.jsondocs/framework/angular/guides/query-retries.mddocs/framework/angular/guides/testing.mdpackages/angular-query-experimental/src/inject-mutation.tspackages/angular-query-experimental/src/create-base-query.ts
📚 Learning: 2025-08-25T19:16:59.365Z
Learnt from: justjake
Repo: TanStack/query PR: 9589
File: packages/query-core/src/queryCache.ts:132-146
Timestamp: 2025-08-25T19:16:59.365Z
Learning: The TypeScript pattern `t satisfies never` in a switch statement's default case is valid for exhaustiveness checking when all possible values of a union type are handled in the switch cases. For `typeof` operations, this ensures all 8 possible return values are covered: "string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function".
Applied to files:
docs/framework/angular/typescript.md
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.
Applied to files:
docs/framework/angular/guides/query-invalidation.mdpackages/angular-query-experimental/src/inject-queries.tspackages/angular-query-experimental/src/inject-query.tspackages/angular-query-experimental/src/query-options.tspackages/angular-query-experimental/src/types.ts
🧬 Code graph analysis (18)
packages/angular-query-experimental/src/__tests__/pending-tasks-ssr.test.ts (1)
packages/angular-query-experimental/src/inject-query.ts (1)
injectQuery(224-232)
packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts (2)
packages/angular-query-experimental/src/inject-infinite-query.ts (1)
injectInfiniteQuery(115-140)packages/query-core/src/types.ts (1)
InfiniteData(204-207)
packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts (1)
packages/angular-query-experimental/src/__tests__/test-utils.ts (1)
setupTanStackQueryTestBed(52-64)
packages/angular-query-experimental/src/__tests__/test-utils.ts (1)
packages/query-core/src/queryObserver.ts (1)
options(379-385)
packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts (1)
packages/angular-query-experimental/src/inject-queries.ts (1)
injectQueries(271-381)
packages/angular-query-experimental/src/__tests__/with-devtools.test.ts (1)
packages/angular-query-experimental/src/__tests__/test-utils.ts (1)
flushQueryUpdates(70-72)
packages/angular-query-experimental/src/__tests__/signal-proxy.test.ts (2)
packages/angular-query-experimental/src/signal-proxy.ts (1)
signalProxy(19-61)packages/angular-query-experimental/src/__tests__/test-utils.ts (1)
registerSignalInput(83-100)
packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts (1)
packages/angular-query-experimental/src/__tests__/test-utils.ts (1)
registerSignalInput(83-100)
packages/angular-query-experimental/src/inject-infinite-query.ts (3)
packages/query-core/src/types.ts (3)
DefaultError(47-51)InfiniteData(204-207)QueryKey(53-61)packages/angular-query-experimental/src/types.ts (1)
CreateInfiniteQueryOptions(69-84)packages/angular-query-experimental/src/signal-proxy.ts (1)
MethodKeys(4-6)
packages/angular-query-experimental/src/__tests__/inject-is-fetching.test.ts (1)
packages/angular-query-experimental/src/__tests__/test-utils.ts (1)
setupTanStackQueryTestBed(52-64)
packages/angular-query-experimental/src/__tests__/inject-is-mutating.test.ts (1)
packages/angular-query-experimental/src/__tests__/test-utils.ts (2)
setupTanStackQueryTestBed(52-64)flushQueryUpdates(70-72)
packages/angular-query-experimental/src/__tests__/mutation-options.test.ts (1)
packages/angular-query-experimental/src/__tests__/test-utils.ts (2)
setupTanStackQueryTestBed(52-64)flushQueryUpdates(70-72)
packages/angular-query-experimental/src/__tests__/inject-mutation-state.test.ts (1)
packages/angular-query-experimental/src/__tests__/test-utils.ts (1)
registerSignalInput(83-100)
packages/angular-query-experimental/src/__tests__/inject-queries.test.ts (2)
packages/angular-query-experimental/src/__tests__/test-utils.ts (1)
setupTanStackQueryTestBed(52-64)packages/angular-query-experimental/src/inject-queries.ts (1)
injectQueries(271-381)
packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts (3)
packages/angular-query-experimental/src/__tests__/test-utils.ts (1)
setupTanStackQueryTestBed(52-64)examples/angular/infinite-query-with-max-pages/src/app/components/example.component.ts (1)
Component(12-54)packages/angular-query-experimental/src/inject-infinite-query.ts (1)
injectInfiniteQuery(115-140)
packages/angular-query-experimental/src/__tests__/pending-tasks.test.ts (1)
packages/angular-query-experimental/src/__tests__/test-utils.ts (2)
setupTanStackQueryTestBed(52-64)flushQueryUpdates(70-72)
packages/angular-query-experimental/src/query-options.ts (1)
packages/angular-query-experimental/src/types.ts (1)
CreateQueryOptions(29-37)
packages/angular-query-experimental/src/types.ts (2)
packages/svelte-query/src/types.ts (3)
CreateBaseQueryOptions(24-30)CreateQueryOptions(39-44)CreateInfiniteQueryResult(68-71)packages/angular-query-experimental/src/signal-proxy.ts (2)
MapToSignals(8-10)MethodKeys(4-6)
🪛 markdownlint-cli2 (0.18.1)
docs/framework/angular/installation.md
10-10: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
🔇 Additional comments (96)
.changeset/deep-crews-open.md (1)
2-2: Verify the version level: should this be "major" instead of "minor"?The PR objectives note that Angular <19 support was removed and Angular v19+ is now required. This is a breaking change for consumers using Angular <19, which typically warrants a
majorversion bump rather thanminor.Confirm whether this changeset should be updated to reflect the breaking nature of the change.
docs/framework/angular/guides/infinite-queries.md (1)
22-22: Approve documentation examples for Angular v19 DI patterns.The additions of
projectsService = inject(ProjectsService)consistently demonstrate Angular's dependency-injection pattern in both examples. The queryFn correctly capturesthisvia arrow function closure to access the injected service. This aligns well with the PR objective to correct examples and include properthis.references, making the documentation clearer for users implementing infinite queries with Angular v19.Also applies to: 78-79
docs/framework/angular/guides/caching.md (1)
30-30: Typo correction approved.The correction from "que yFn" to "queryFn" improves clarity in the documentation narrative.
examples/angular/infinite-query-with-max-pages/src/app/components/example.component.ts (1)
32-53: Nice simplification—direct query API access eliminates duplication.The refactor from private state mirrors to direct query method calls (
hasNextPage(),isFetchingNextPage(), etc.) is clean and correct. All methods are properly invoked as signals withincomputed(), establishing the right reactive dependencies. This aligns well with the signal-based improvements in Angular 19.docs/framework/angular/guides/testing.md (2)
32-32: Clear guidance on test setup patterns.The expansion of the
afterEachsection effectively communicates the rationale for preferring a freshQueryClientper test over reusing and clearing, emphasizing explicit setup over "invisible globals." This aligns well with the PR's emphasis on deterministic, lifecycle-aware testing.
47-47: Add version-specific guidance for effect triggering in Angular 19 vs. 20+.Examples at lines 47 and 140 use
TestBed.tick()to trigger effects, but this API was introduced in Angular 20. Since this documentation targets Angular 19+, provide guidance for Angular 19 users (e.g., useTestBed.flushEffects()orTestBed.inject(ApplicationRef).tick()) to ensure examples work across supported versions.docs/framework/angular/guides/disabling-queries.md (2)
16-21: Template syntax leverages Angular 19 control flow with proper signal binding.The change from direct signal calls inside
@forto bindingquery.data()once via@if (query.data(); as data)is a best practice for signal-based components. This avoids redundant signal reads and improves change detection efficiency.
73-73: Import path aligns with Angular Query experimental package migration.The @tanstack/angular-query-experimental package offers a 1st-class API for using TanStack Query via Angular. All Angular guide examples consistently import injectQuery and queryOptions from @tanstack/angular-query-experimental. This import source is used uniformly across all Angular documentation examples, guides, and quick-start materials.
packages/angular-query-experimental/package.json (2)
104-105: Test coverage aligns correctly with Angular 19 requirements.The peerDependencies now require Angular >=19.0.0, and test scripts only cover TypeScript 5.5+. This is correct: Angular 19 dropped support for TypeScript versions below 5.5, so the testing strategy appropriately covers the supported range.
91-91: @angular/platform-server belongs in devDependencies.The package is correctly placed as a development dependency since it's used only for SSR testing with PendingTasks integration, not in runtime code. The library's runtime exports use @angular/core, HttpClient, and @angular/common/http, not @angular/platform-server.
docs/framework/angular/reference/functions/injectQuery.md (1)
12-21: LGTM! Consistent use oflastValueFromfor Observable-to-Promise conversion.The examples correctly demonstrate wrapping Angular's HttpClient observables with
lastValueFromto return a Promise, which aligns with TanStack Query's expectedqueryFnreturn type.docs/framework/angular/guides/paginated-queries.md (1)
38-41: Good migration to boolean signal methods.Using
query.isPending()andquery.isError()instead of status-based checks aligns with the updated TypeScript narrowing guidance and improves type inference in Angular templates.docs/framework/angular/typescript.md (2)
95-97: Clear and accurate guidance on TypeScript narrowing limitations.The explanation correctly notes that TypeScript doesn't support discriminated unions on object methods, and the recommendation to use boolean signal methods (
isSuccess(),isError(),isPending()) is the right workaround for Angular's signal-based architecture.
155-171: Improved defaultError example with practical AxiosError usage.Using
AxiosErrorinstead ofunknownas thedefaultErrortype provides a more realistic and useful example of module augmentation for error typing.docs/framework/angular/guides/dependent-queries.md (1)
12-23: Good update to use instance-bound methods.Using
this.email(),this.getUserByEmail, andthis.getProjectsByUsercorrectly demonstrates class-based Angular component patterns and is consistent with the rest of the documentation updates.packages/angular-query-experimental/src/inject-infinite-query.ts (2)
142-146: LGTM! Correctly excludes action methods from signal conversion.The
methodsToExcludearray properly identifiesfetchNextPage,fetchPreviousPage, andrefetchas methods that should remain as regular functions rather than being wrapped in signals. This prevents early signal reads and maintains the expected imperative API for these action methods.
115-139: Clean integration with the signal proxy exclusion mechanism.The implementation properly passes
methodsToExcludetocreateBaseQuery, maintaining consistency with theinjectQueryimplementation. The generic type parameters are well-structured with appropriate defaults.packages/angular-query-experimental/src/signal-proxy.ts (3)
4-10: Well-designed type utilities for selective signal exclusion.The
MethodKeysutility correctly extracts function property names, and the updatedMapToSignalstype conditionally preserves original function types for excluded fields while converting others to signals. This provides accurate type inference for consumers.
34-41: Correct use ofuntrackedfor excluded methods.Wrapping the function call in
untracked(inputSignal)[prop]ensures that calling these methods (likerefetch) doesn't create a reactive dependency on the input signal. This prevents the issue of reading input signals too early during component initialization, as mentioned in the PR objectives.
47-58: Consider usinguntrackedconsistently inownKeyshandler.The
hashandler at line 48 andownKeyshandler at line 51 correctly useuntrackedto avoid creating reactive dependencies. This is consistent and appropriate for these metadata operations.docs/framework/angular/guides/queries.md (1)
22-24: LGTM! Good documentation improvement.Adding the
@Componentdecorator provides better context for the example, making it clearer thatTodosComponentis a complete Angular component.packages/angular-query-experimental/README.md (2)
81-84: LGTM! Complete NgModule example.Adding
provideHttpClient()and theAppModuleexport makes this a more complete, copy-pasteable example. TheprovideHttpClient()addition is particularly helpful since many users will need HTTP client for their query functions.
32-32: Clarify Angular version requirement discrepancy.The README correctly reflects the package.json peer dependencies (Angular 19+). However, official TanStack Query documentation states the adapter requires Angular 16 or higher. Verify this upgrade from 16+ to 19+ is intentional and update the package.json comment or documentation if needed to explain the minimum requirement.
packages/angular-query-experimental/src/__tests__/with-devtools.test.ts (1)
16-16: LGTM! Test utility import.Importing the centralized
flushQueryUpdatesutility is consistent with the test refactoring pattern used across the test suite.docs/framework/angular/guides/does-this-replace-client-state.md (1)
10-11: LGTM! Angular-specific terminology.Replacing React-centric state management references (Redux, MobX, Zustand) with Angular equivalents (NgRx Store, RxJS) makes the documentation more relevant and relatable for Angular developers.
packages/angular-query-experimental/src/__tests__/inject-devtools-panel.test.ts (1)
1-6: LGTM! Centralized test utility imports.Switching to
setupTanStackQueryTestBedreduces boilerplate and improves consistency across the test suite.docs/framework/angular/overview.md (2)
16-16: LGTM! Angular 19+ requirement.The version requirement update is consistent across all documentation files in this PR and aligns with the package's new minimum Angular version.
76-80: LGTM! Modern Angular Query patterns.The updated template demonstrates best practices:
- Using
isError()andisSuccess()status methods for better type discrimination- Leveraging Angular 19's
@letsyntax for local template variables- Improved type narrowing by checking status before accessing data
These changes provide a better example for users to follow.
packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts (1)
1-96: LGTM! Comprehensive type coverage for discriminated unions.The new type tests thoroughly validate:
- Default union types for
dataanderrorsignals- Type narrowing when checking
isSuccess(),isPending(), andisError()- Correct typing for the
selectfunction parameter and return typeThis provides strong type safety guarantees and aligns with the discriminated union improvements mentioned in the PR objectives.
packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts (1)
36-46: LGTM! Select function type coverage.The new test validates that:
- The
selectfunction receives the correct input type (string from queryFn)- The returned data signal correctly reflects the transformed type (
Signal<number | undefined>)This strengthens type safety guarantees for the select transformation feature.
packages/angular-query-experimental/src/__tests__/inject-queries.test-d.ts (1)
179-262: LGTM! Comprehensive type tests for the combine function.These tests thoroughly cover the typing scenarios for
injectQuerieswith thecombineoption:
- Validates correct data types in the combine callback
- Confirms
refetchis callable (aligned with themethodsToExcludepattern)- Tests branded result types with
Signalwrapper- Verifies
initialDatacorrectly removesundefinedfrom the data typedocs/framework/angular/guides/initial-query-data.md (2)
84-91: LGTM! Correctly updated to component-scoped patterns.The changes properly add
this.prefix for component-scoped access toqueryClientand use dynamictodoId()in the fetch path, aligning with Angular component conventions throughout the documentation.
97-108: Verify queryKey consistency across examples.Line 99 uses
queryKey: ['todos', this.todoId()]while line 83 usesqueryKey: ['todo', this.todoId()](singular vs plural). This may be intentional to demonstrate different patterns, but verify this is the intended behavior.docs/framework/angular/guides/mutations.md (1)
246-256: LGTM! Improved component example with proper Angular conventions.The changes correctly:
- Add
@Componentdecorator making it a complete Angular component example- Rename class to
SomeComponentfollowing PascalCase conventions- Use
this.mutation.mutate()for proper component-scoped accesspackages/angular-query-experimental/src/__tests__/pending-tasks-ssr.test.ts (2)
20-28: LGTM! Proper test lifecycle setup.Good use of
destroyPlatform()for cleanup between tests and fake timers setup/teardown. This ensures test isolation for SSR scenarios.
46-71: Well-structured SSR integration test.The test correctly:
- Bootstraps with zoneless change detection and server rendering
- Configures QueryClient with
retry: falseto avoid flakiness- Uses
vi.runAllTimersAsync()before awaiting the HTML promise to properly advance fake timers- Verifies the query data appears in the server-rendered output
This validates that Angular's
PendingTasksintegration works correctly with TanStack Query during SSR.docs/framework/angular/guides/invalidations-from-mutations.md (1)
5-10: LGTM!The documentation updates appropriately align the example with Angular conventions by adding the
@Componentdecorator and expanding the replacement mapping for better React-to-Angular translation.Also applies to: 30-33
docs/framework/angular/guides/query-invalidation.md (1)
11-16: LGTM!The addition of the
@Componentdecorator and proper Angular imports makes the example more representative of real-world Angular usage.packages/angular-query-experimental/src/__tests__/inject-is-mutating.test.ts (1)
3-6: LGTM!The migration to shared test utilities (
setupTanStackQueryTestBedandflushQueryUpdates) appropriately centralizes test setup logic and improves maintainability.Also applies to: 15-15, 38-38
packages/angular-query-experimental/src/__tests__/inject-is-fetching.test.ts (1)
3-6: LGTM!Consistent migration to the shared test utility pattern, maintaining test behavior while improving code organization.
Also applies to: 15-15
docs/framework/angular/guides/query-options.md (1)
34-34: LGTM!The added example effectively demonstrates how to use
QueryClientmethods (prefetchQueryandsetQueryData) withqueryOptions, providing helpful guidance for readers.Also applies to: 36-43
docs/framework/angular/guides/query-retries.md (1)
33-37: LGTM!The documentation correctly updates to use
provideTanStackQueryandbootstrapApplication, aligning with the Angular Query integration pattern.Also applies to: 54-54
packages/angular-query-experimental/src/__tests__/mutation-options.test.ts (1)
11-11: LGTM!Consistent application of the test utilities pattern across all test cases, replacing direct timer manipulation with the abstracted
flushQueryUpdates()helper.Also applies to: 19-19, 58-58, 78-78, 106-106, 134-134
packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts (1)
22-67: LGTM!The component-based testing approach with
ChangeDetectionStrategy.OnPushprovides more realistic test coverage and aligns well with the PR's goal of testing Angular Query in component contexts.docs/framework/angular/guides/query-functions.md (1)
12-84: LGTM! Documentation correctly demonstrates signal-based query patterns.The examples consistently show signal function call syntax (e.g.,
todoId(),this.todoId()) for reactive query keys and query functions, which aligns with Angular's signal-based reactivity model and the broader changes in this PR.packages/angular-query-experimental/src/__tests__/inject-queries.test.ts (3)
19-25: LGTM! Test setup properly uses fake timers.The addition of
vi.useFakeTimers({ shouldAdvanceTime: true })in beforeEach andvi.useRealTimers()in afterEach ensures proper test isolation and timer control for async operations.
83-158: Excellent test coverage for the combine function.This test thoroughly validates:
- Combining multiple query results into a custom shape
- The refetch method from the combined result
- Progressive data updates (empty → partial → complete)
- 5 distinct snapshots showing data progression through refetch cycles
The test correctly verifies both the combined data string format and the refetch functionality.
160-234: Comprehensive test for dynamic queries array.This test validates important reactive behaviors:
- Dynamic addition/removal of queries via signal updates
- Correct data mapping and aggregation
- Multiple change detection cycles (7 and 9 snapshots respectively)
- Edge case of empty queries array
The test correctly exercises the reactive nature of the queries array and verifies that the UI updates appropriately.
packages/angular-query-experimental/src/query-options.ts (1)
44-48: LGTM! Type simplification enables select function support.Removing the
Omit<..., 'queryFn'>wrapper and usingCreateQueryOptionsdirectly reintroduces thequeryFnproperty intoDefinedInitialDataOptions. This change aligns with other signal-based adapters and fixes the select function on queries as noted in the PR objectives.docs/framework/angular/guides/default-query-function.md (1)
31-54: LGTM! Documentation correctly demonstrates component-based query usage.The addition of
@Componentdecorators and the use of Angular 19'sinput()signal pattern make the examples more complete and realistic. The transition frompostIdSignal()topostId()is consistent with the signal input API.packages/angular-query-experimental/src/__tests__/inject-mutation-state.test.ts (1)
161-181: LGTM! Host component pattern properly tests signal inputs.The introduction of
HostComponentwithregisterSignalInputcorrectly enables testing of components with required signal inputs in Angular's new testing paradigm. The use ofnativeElement.querySelectorAllfor DOM queries is appropriate for this test scenario.packages/angular-query-experimental/src/__tests__/signal-proxy.test.ts (2)
18-18: Note the exclusion mechanism.The signalProxy now accepts a second argument
['fn']to specify which fields should NOT be converted to signals. This is a key change enabling the refactored proxy behavior described in the PR objectives.
63-95: Excellent component fixture tests for signal proxy behavior.These tests thoroughly validate:
- Fields are generated lazily after first change detection
- Excluded fields (fn) remain functions while others become signals
- Short accessors correctly reference the proxy fields
- Proxy fields reactively update when the underlying signal changes
The tests properly exercise the signal proxy in a realistic Angular component context with OnPush change detection.
packages/angular-query-experimental/src/inject-query.ts (1)
230-234: LGTM! Method exclusion mechanism correctly implemented.The introduction of
methodsToExcludewith['refetch']ensures that the refetch method remains a function rather than being converted to a signal. This prevents issues with reading input signals too early (as mentioned in PR objectives) and maintains the expected API surface whererefetchis called as a function.The type safety via
Array<MethodKeys<QueryObserverResult>>ensures only valid method names can be excluded.docs/framework/angular/guides/parallel-queries.md (1)
20-62: LGTM! Documentation examples correctly demonstrate parallel queries.The addition of
@Componentdecorators makes the examples more complete and realistic. The experimental notice forinjectQueriesappropriately sets user expectations.packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts (3)
1-15: LGTM!Import updates are appropriate:
ChangeDetectionStrategyfor OnPush components,firstValueFromfor RxJS observable handling, andregisterSignalInputfrom test utilities.
302-354: LGTM!The host-wrapper pattern for testing signal inputs is well-structured. Using
registerSignalInputto mark the input as signal-based before creating the fixture ensures proper Angular change detection behavior.
661-704: LGTM!The optimistic updates test properly validates the pending tasks lifecycle:
- Verifies optimistic update applies synchronously
- Confirms
app.isStableisfalsewhile mutation is pending- Verifies completion after
whenStable()resolvesThis effectively tests the PendingTasks integration for SSR and stability tracking.
packages/angular-query-experimental/src/__tests__/test-utils.ts (3)
48-64: LGTM!
setupTanStackQueryTestBedprovides a clean abstraction for test setup, properly accepting optional additional providers viaEnvironmentProviders | Providerunion.
66-72: LGTM!Clear documentation explaining why advancing timers by 0 is needed for TanStack Query's notifyManager updates.
76-99: LGTM with note on internal API usage.The
registerSignalInputfunction correctly documents its temporary nature using the theta (ɵ) prefix, indicating Angular's experimental APIs. The error handling for missing component definitions is appropriate. The ɵcmp and ɵdir fields are standard component/directive definitions generated by Angular's Ivy compiler, and while internal, they remain valid in Angular 19. The comment about Angular 21 CLI supporting Vitest compilation is accurate—Vitest is now promoted to stable as the default test runner in Angular v21.docs/framework/angular/guides/placeholder-query-data.md (3)
10-19: LGTM!The example now properly shows the Angular component wrapper around the
injectQueryusage.
27-40: LGTM!Good example demonstrating the reactive pattern with
signal()fortodoId, showing how bothqueryKeyandqueryFncan depend on the signal value.
45-65: LGTM!Good example showing
input.required()usage with queries and how to access cached data fromQueryClientfor placeholder data.packages/angular-query-experimental/src/inject-mutation.ts (4)
1-11: LGTM!Import change from custom
PENDING_TASKSto Angular's nativePendingTasksis the right approach for Angular 19+ compatibility.
84-98: LGTM!The pending task lifecycle helpers are well-guarded:
startPendingTaskprevents double-start with!taskCleanupRef && !destroyedstopPendingTaskproperly nullifies the ref after invoking cleanup
141-181: LGTM!The subscriber callback properly:
- Guards against destroyed state before processing
- Tracks pending tasks based on
isPendingstate- Cleans up in correct order: set
destroyed=true, stop pending task, then unsubscribe
196-200: LGTM!The
excludeFunctionsparameter correctly lists the imperative methods (mutate,mutateAsync,reset) that should remain callable functions rather than being wrapped as signals.packages/angular-query-experimental/src/create-base-query.ts (7)
1-25: LGTM!Import updates properly bring in Angular's native APIs (
DestroyRef,PendingTasks,linkedSignal) and the necessary type imports for the refactored implementation.
86-93: LGTM!The lazy initialization pattern is well-designed:
computed()creates the observer only when first accesseduntracked(defaultedOptionsSignal)prevents the computed from tracking option changes- The separate effect handles option synchronization after creation
95-127: LGTM!The result tracking implementation correctly integrates with TanStack Query's property tracking optimization. The
void valuepattern (line 125) idiomatically signals that the access is intentional for tracking purposes.
180-194: LGTM!The dual cleanup strategy is robust:
- Effect's
onCleanuphandles normal effect lifecycle cleanupdestroyRef.onDestroyensures cleanup even if effect cleanup doesn't run (edge cases)The
isRestoring()guard correctly prevents subscription during hydration/restore scenarios.
196-199: LGTM!Using
resultSignal.asReadonly()properly encapsulates the signal state, and theexcludeFunctionsparameter correctly propagates tosignalProxy.
169-178:linkedSignalis available in Angular 19 (experimental) and became stable in Angular 20.LinkedSignal was introduced in Angular Version 19, though it was promoted to stable in Angular 20. The code using
linkedSignalis compatible with Angular 19 but will have experimental status at that version level.
129-167: The destroyed check timing is correct and already verified by tests.The
destroyedcheck at line 144 prevents stale updates by executing inside the queued microtask before state modifications. Test coverage inpending-tasks.test.tsexplicitly validates this behavior with dedicated component destruction tests that confirm pending tasks are cleaned up and Angular stability is restored when components with active queries or mutations are destroyed.packages/angular-query-experimental/src/__tests__/inject-query.test.ts (7)
1-31: LGTM! Imports properly updated for component-based testing.The imports now include
ChangeDetectionStrategy,NgZone, andregisterSignalInputto support the new component-wrapped test approach with OnPush change detection.
53-260: Well-structured type inference test with comprehensive coverage.The refactoring to a component-based approach allows all type inference tests to run within a proper Angular injection context. The tests cover:
- Unspecified queryFn defaulting to unknown
- Explicit generic type parameters
- Union types, wrapped queries, and various queryFn signatures
578-619: Proper error handling cleanup for uncaughtException listener.The error handling tests correctly manage the
process.on('uncaughtException')listener lifecycle with a try/finally block ensuring cleanup even if the test fails. This prevents listener leaks across tests.
726-747: Good test for effect ordering with query injection.This test validates an important edge case: effects registered before
injectQueryshould be able to safely read query data without throwing. The spy correctly verifies the initial undefined state.
749-785: Excellent test for synchronous input availability.This test validates that when
setInputis called before change detection, the query can immediately access the input signal value and return cached data. This is important for avoiding unnecessary pending states with pre-populated cache.
827-845: Good test for same-macrotask data updates.Uses
TestBed.tick()to trigger effects (valid Angular 20+ API) and validates that query data updates are reflected within the same macrotask after flushing microtasks. Based on learnings,TestBed.tick()is the appropriate API for triggering effects in unit tests.
884-914: Validates PendingTasks integration correctly.This test ensures that
whenStable()waits for query completion via the PendingTasks integration. The pattern of advancing timers and then awaitingwhenStable()correctly tests the async coordination.packages/angular-query-experimental/src/inject-queries.ts (4)
95-111: Clean generic wrapper for initialData type resolution.
GenericGetDefinedOrUndefinedQueryResultelegantly abstracts the initialData logic to work with any result type pair, eliminating code duplication betweenGetCreateQueryResultandGetQueryObserverResult.
113-143: Well-structured type inference for data and error types.
InferDataAndErrorconsolidates the type inference logic shared between signal-wrapped results and raw observer results, following the same three-part pattern (object form, tuple form, queryFn inference) used inGetCreateQueryOptionsForCreateQueries.
236-264: Appropriate type change for combine callback.
RawQueriesResultscorrectly maps to plainQueryObserverResulttypes for the combine function, as the combine callback receives raw observer results rather than signal-proxied values. This aligns with how other adapters (Vue) handle the combine function.
374-379: Thepromiseproperty needs special handling, but cannot be excluded via the existing mechanism.
QueryObserverResultdoes have apromiseproperty (typePromise<TData>) that is currently wrapped asSignal<Promise<TData>>bysignalProxy. However, it cannot be added to the['refetch']exclusion list becausesignalProxyonly accepts function properties in itsexcludeFieldsparameter—the typeMethodKeys<T>explicitly filters to functions only.This creates an issue: the
promiseproperty violates TanStack Query's "stable promise" contract (documented as requiringexperimental_prefetchInRenderand meant forReact.use()), since wrapping it as a signal makes it reactive rather than stable. Users must call.promise()to access the wrapped signal, breaking compatibility with the documented usage pattern.Resolving this requires expanding
signalProxyto support excluding non-function properties, or implementing alternative handling for Promise-type properties specifically.packages/angular-query-experimental/src/__tests__/pending-tasks.test.ts (5)
15-42: Good test setup with centralized configuration.Using
setupTanStackQueryTestBedand resettingonlineManager.setOnline(true)in afterEach ensures consistent test isolation. The helper reduces boilerplate and ensures consistent module configuration across tests.
219-265: Excellent test for offline-start edge case.This test validates a subtle but important scenario: when a query initializes while offline with
networkMode: 'online', it goes directly topausedwithout ever reachingfetching. The test correctly verifies that PendingTasks still blocks stability until the app comes back online and the query completes.
400-448: Well-structured concurrent queries test.Using a single component with multiple query properties provides clean access via
fixture.componentInstanceand properly tests that all concurrent queries complete beforewhenStable()resolves.
537-542: Clean provider composition with setupTanStackQueryTestBed.The
providersoption correctly layers HttpClient testing providers on top of the base TanStack Query configuration, maintaining separation of concerns.
356-392: fixture.isStable() appropriately checks fixture-level pending tasks.The destruction tests correctly use
fixture.isStable()andfixture.whenStable()to verify pending tasks cleanup. ComponentFixture.isStable() returns !this.pendingTasks.hasPendingTasks, and TanStack Query's inject* functions integrate with PendingTasks which ensures the framework is aware of in-progress queries and mutations. This pattern is explicitly documented as the recommended approach for testing query/mutation completion.packages/angular-query-experimental/src/types.ts (5)
19-19: Appropriate import addition for MethodKeys.Importing
MethodKeysalongsideMapToSignalsenables the type system to correctly identify and exclude method properties from signal conversion.
21-37: Simplified type aliases align with Svelte adapter pattern.Changing
CreateBaseQueryOptionsandCreateQueryOptionsfrom interfaces to type aliases matches the pattern used inpackages/svelte-query/src/types.ts(as shown in the relevant code snippets), promoting consistency across framework adapters.
86-94: Correct MapToSignals usage with MethodKeys.The pattern
MapToSignals<T, MethodKeys<T>>ensures that method properties (likerefetch,promise) remain as callable functions rather than being wrapped in signals. TheOmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>correctly excludes the narrowing predicates before applying the transformation.
266-282: Mutation result type correctly updated.
CreateMutationResultproperly appliesMapToSignalswithMethodKeyswhile excludingBaseMutationNarrowingpredicates, maintaining consistency with the query result types.
111-130: Consistent MethodKeys pattern for infinite query results.Both
CreateInfiniteQueryResultandDefinedCreateInfiniteQueryResultcorrectly apply theMethodKeyspattern. Note thatDefinedCreateInfiniteQueryResultdoesn't includeBaseQueryNarrowingin its definition, which differs from the non-infinite variants.Verify this is intentional - the defined infinite query result type does not include the
isSuccess/isError/isPendingnarrowing predicates:#!/bin/bash # Check if DefinedCreateInfiniteQueryResult should include BaseQueryNarrowing rg -n "DefinedCreateInfiniteQueryResult" --type=ts packages/angular-query-experimental/src/
| userIds = injectQuery(() => ({ | ||
| queryKey: ['users'], | ||
| queryFn: getUserData, | ||
| select: (users) => users.map((user) => user.id), | ||
| })) | ||
|
|
||
| // Then get the users messages | ||
| userQueries = injectQueries(() => ({ | ||
| queries: (this.userIds() ?? []).map((userId) => ({ | ||
| queryKey: ['user', userId], | ||
| queryFn: () => getUserById(userId), | ||
| })), | ||
| })) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect data access pattern in injectQueries example.
Line 43 uses this.userIds() but userIds is the query result object from injectQuery, not a signal of the data. To access the selected user IDs, it should be this.userIds.data().
🔎 Proposed fix
// Then get the users messages
userQueries = injectQueries(() => ({
- queries: (this.userIds() ?? []).map((userId) => ({
+ queries: (this.userIds.data() ?? []).map((userId) => ({
queryKey: ['user', userId],
queryFn: () => getUserById(userId),
})),
}))📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| userIds = injectQuery(() => ({ | |
| queryKey: ['users'], | |
| queryFn: getUserData, | |
| select: (users) => users.map((user) => user.id), | |
| })) | |
| // Then get the users messages | |
| userQueries = injectQueries(() => ({ | |
| queries: (this.userIds() ?? []).map((userId) => ({ | |
| queryKey: ['user', userId], | |
| queryFn: () => getUserById(userId), | |
| })), | |
| })) | |
| userIds = injectQuery(() => ({ | |
| queryKey: ['users'], | |
| queryFn: getUserData, | |
| select: (users) => users.map((user) => user.id), | |
| })) | |
| // Then get the users messages | |
| userQueries = injectQueries(() => ({ | |
| queries: (this.userIds.data() ?? []).map((userId) => ({ | |
| queryKey: ['user', userId], | |
| queryFn: () => getUserById(userId), | |
| })), | |
| })) |
🤖 Prompt for AI Agents
In docs/framework/angular/guides/dependent-queries.md around lines 35 to 47, the
injectQueries example incorrectly calls this.userIds() (userIds is a query
result object), so update the code to read the selected IDs from the query
result by using this.userIds.data() when mapping; ensure you also keep a safe
fallback like (this.userIds.data() ?? []) so the map runs on an array.
| @Component({ | ||
| // ... | ||
| }) | ||
| export class PaginationExampleComponent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate @Component decorator appears to be unintentional.
There's already a complete @Component decorator with the full template at lines 26-70. This second, empty @Component({ // ... }) block creates invalid Angular code since a class cannot have two decorators of the same type.
🔎 Proposed fix
</div>
`,
})
-
-@Component({
- // ...
-})
export class PaginationExampleComponent {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Component({ | |
| // ... | |
| }) | |
| export class PaginationExampleComponent { | |
| `, | |
| }) | |
| export class PaginationExampleComponent { |
🤖 Prompt for AI Agents
In docs/framework/angular/guides/paginated-queries.md around lines 71 to 75
there is a duplicate, empty @Component decorator applied to
PaginationExampleComponent which is invalid; remove the second @Component({ //
... }) block so the class only has the original complete @Component decorator
(lines ~26-70) and ensure the class definition follows that single decorator.
| [//]: # 'DynamicParallelIntro' | ||
| [//]: # 'Example2' | ||
|
|
||
| > IMPORTANT: `injectQueries` is experimental and is provided in it's own entry point |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor grammatical correction needed.
Change "it's own entry point" to "its own entry point" (possessive form, not contraction).
🔎 Proposed fix
-> IMPORTANT: `injectQueries` is experimental and is provided in it's own entry point
+> IMPORTANT: `injectQueries` is experimental and is provided in its own entry point📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| > IMPORTANT: `injectQueries` is experimental and is provided in it's own entry point | |
| > IMPORTANT: `injectQueries` is experimental and is provided in its own entry point |
🤖 Prompt for AI Agents
In docs/framework/angular/guides/parallel-queries.md at line 44, the phrase
"it's own entry point" uses the contraction "it's" incorrectly; change it to the
possessive "its own entry point" to correct the grammar.
| ### NPM | ||
|
|
||
| _Angular Query is compatible with Angular v16 and higher_ | ||
| _Angular Query is compatible with Angular v19 and higher_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use blockquote format instead of emphasis for the compatibility note.
The compatibility update to Angular v19+ is correct and aligns with the PR objectives. However, the current emphasis formatting using underscores triggers a markdown linting rule (MD036) that discourages using emphasis as a heading/callout. Use a blockquote format instead for better semantic clarity and linting compliance.
🔎 Proposed fix using blockquote format
-_Angular Query is compatible with Angular v19 and higher_
+> Angular Query is compatible with Angular v19 and higher📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| _Angular Query is compatible with Angular v19 and higher_ | |
| > Angular Query is compatible with Angular v19 and higher |
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
10-10: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
🤖 Prompt for AI Agents
In docs/framework/angular/installation.md at line 10, the compatibility note
currently uses emphasis underscores ("_Angular Query is compatible with Angular
v19 and higher_") which triggers MD036; replace that emphasis with a markdown
blockquote (prefix the line with "> ") so the note becomes a proper callout and
satisfies markdown linting.
| <button (click)="addItem()">Create</button> | ||
| <ul> | ||
| @for (task of tasks.data(); track task) { | ||
| @for (task of tasks.data(); track $index) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revert to tracking by task value for correct optimistic update behavior.
Tracking by $index instead of the task value can cause incorrect DOM updates during optimistic updates and rollbacks. When an optimistically added item is rolled back, Angular may incorrectly reuse DOM nodes because it tracks by position rather than identity, potentially displaying stale or wrong data.
For dynamic lists with add/remove operations—especially in an optimistic updates example—tracking by a stable identifier or the value itself ensures correct change detection.
🔎 Proposed fix
- @for (task of tasks.data(); track $index) {
+ @for (task of tasks.data(); track task) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @for (task of tasks.data(); track $index) { | |
| @for (task of tasks.data(); track task) { |
🤖 Prompt for AI Agents
In
examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts
around line 39, the ng-for/loop is tracking list items by $index which breaks
optimistic add/remove/rollback behavior; update the loop to track by the task
identity (preferably a stable id like task.id, or the task value if no id
exists) so Angular/Svelte will use item identity instead of position when
diffing and DOM updates will reflect correct optimistic rollbacks.
| }, | ||
| ) | ||
|
|
||
| TestBed.tick() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat packages/angular-query-experimental/package.json | jq '.peerDependencies."@angular/core"'Repository: TanStack/query
Length of output: 68
TestBed.tick() requires Angular 20, but peer dependency allows Angular 19.
TestBed.tick() was introduced in Angular 20, but the package declares @angular/core >= 19.0.0 as a peer dependency. Using TestBed.tick() will fail on Angular 19. Either update the peer dependency to require Angular 20+ or switch to an alternative approach compatible with Angular 19 (e.g., TestBed.flushEffects() for Angular 19, with a version check if needed).
🤖 Prompt for AI Agents
In
packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts
around line 99, the test calls TestBed.tick() which is only available in Angular
20+, but the package peer dependency allows Angular 19; replace the
TestBed.tick() call with a compatible alternative or gate it behind a
runtime/version check: either (A) bump the peer dependency to require
@angular/core >=20.0.0 and keep TestBed.tick(), or (B) change the test to use
TestBed.flushEffects() (or another Angular 19-compatible API) and add a small
runtime feature-detect/version check so the test calls flushEffects() on Angular
19 and tick() on Angular 20+, ensuring the test runs across the declared peer
dependency range.
🎯 Changes
This is a continuation of #9893, where the main new changes added are:
data = query.datato fail since it would read the input signal to do the check, and in Angular input signals can't be read in the component initialization.DefinedInitialDataOptions, removing the override ofqueryFn. This change fixes the select function on queries and aligns the implementation with the rest of the signal based adapters.I also added more tests, changed some files and type tests that aren't needed in angular v19 and up, and went thought the docs to improve the consistencies and recommendations given the current implementation.
For the docs, the main improvements were removing the recommendation of discriminating with the status signal since it is not type safe in this adapter, removing examples and a note that hinted on RxJS support for query functions, and adding missing
this.and signal calls on some examples.Before reviews, I want to add new tests, specially for the
createBaseQuerychanges on #9893, where the value is ready after effects instead on after init. So I'm leaving this PR as draft until that.✅ Checklist
pnpm run test:pr.🚀 Release Impact
Summary by CodeRabbit
Release Notes
New Features
injectQueriesAPI for dynamic parallel query patterns.Breaking Changes
lastValueFrom()to convert HTTP observables to promises.Documentation
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.