### Install with Bun Source: https://tanstack.com/query/v5/docs/framework/angular/installation.md Use this command to install the library with bun. Compatible with Angular v16 and higher. ```bash bun add @tanstack/angular-query-experimental ``` -------------------------------- ### Basic Example Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/injectQuery.md A basic example demonstrating how to use injectQuery to fetch data from a GitHub repository. ```APIDOC ## Basic example ```ts class ServiceOrComponent { query = injectQuery(() => ({ queryKey: ['repoData'], queryFn: () => this.#http.get('https://api.github.com/repos/tanstack/query'), })) } ``` ``` -------------------------------- ### Install with Yarn Source: https://tanstack.com/query/v5/docs/framework/angular/installation.md Use this command to install the library with yarn. Compatible with Angular v16 and higher. ```bash yarn add @tanstack/angular-query-experimental ``` -------------------------------- ### Install with NPM Source: https://tanstack.com/query/v5/docs/framework/angular/installation.md Use this command to install the library with npm. Compatible with Angular v16 and higher. ```bash npm i @tanstack/angular-query-experimental ``` -------------------------------- ### Install with PNPM Source: https://tanstack.com/query/v5/docs/framework/angular/installation.md Use this command to install the library with pnpm. Compatible with Angular v16 and higher. ```bash pnpm add @tanstack/angular-query-experimental ``` -------------------------------- ### Basic Example Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/injectQuery.md A basic example demonstrating how to use injectQuery to fetch repository data from the GitHub API within an Angular service or component. ```APIDOC ## Basic Example ```ts class ServiceOrComponent { query = injectQuery(() => ({ queryKey: ['repoData'], queryFn: () => this.#http.get('https://api.github.com/repos/tanstack/query'), })) } ``` ``` -------------------------------- ### Angular Root Component Setup Source: https://tanstack.com/query/v5/docs/framework/angular/examples/infinite-query-with-max-pages Sets up the root Angular component, importing the necessary ExampleComponent. Ensure ExampleComponent is correctly defined and imported. ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { ExampleComponent } from './components/example.component' @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-root', template: ``, imports: [ExampleComponent], }) export class AppComponent {} ``` -------------------------------- ### API Fetch Examples Source: https://tanstack.com/query/v5/docs/framework/angular/guides/infinite-queries.md Demonstrates sequential API calls to fetch paginated data using a cursor. ```tsx fetch('/api/projects?cursor=0') // { data: [...], nextCursor: 3} fetch('/api/projects?cursor=3') // { data: [...], nextCursor: 6} fetch('/api/projects?cursor=6') // { data: [...], nextCursor: 9} fetch('/api/projects?cursor=9') // { data: [...] } ``` -------------------------------- ### Angular Root Component Setup Source: https://tanstack.com/query/v5/docs/framework/angular/examples/devtools-panel This is the main application component in Angular. It sets up basic navigation links to different examples of the devtools panel, including a basic and a lazy-loaded version. Ensure you have Angular routing configured to navigate to these paths. ```typescript import { ChangeDetectionStrategy, Component, } from '@angular/core' import { RouterLink, RouterOutlet } from '@angular/router' @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-root', template: ` `, imports: [RouterOutlet, RouterLink], }) export class AppComponent {} ``` -------------------------------- ### Angular Root Component Setup Source: https://tanstack.com/query/v5/docs/framework/angular/examples/simple Defines the root component for an Angular application. Ensure the SimpleExampleComponent is correctly imported and available. ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { SimpleExampleComponent } from './components/simple-example.component' @Component({ selector: 'app-root', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SimpleExampleComponent], template: ``, }) export class AppComponent {} ``` ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { SimpleExampleComponent } from './components/simple-example. component' @Component({ selector: 'app-root', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SimpleExampleComponent], template: ``, }) export class AppComponent {} ``` ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { SimpleExampleComponent } from './components/simple-example.component' @Component({ selector: 'app-root', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SimpleExampleComponent], template: ``, }) export class AppComponent {} ``` -------------------------------- ### Reactive Example Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/injectQuery.md An example showing how injectQuery can be used reactively with Angular signals. The query is enabled and executed based on the state of a signal. ```APIDOC ## Reactive example ```ts class ServiceOrComponent { filter = signal('') todosQuery = injectQuery(() => ({ queryKey: ['todos', this.filter()], queryFn: () => fetchTodos(this.filter()), // Signals can be combined with expressions enabled: !!this.filter(), })) } ``` ``` -------------------------------- ### Angular Root Component Setup Source: https://tanstack.com/query/v5/docs/framework/angular/examples/pagination This is the main application component in Angular. It imports and uses the ExampleComponent, which would contain the TanStack Query logic for pagination. ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { ExampleComponent } from './components/example.component' @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-root', template: ``, imports: [ExampleComponent], }) export class AppComponent {} ``` ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { ExampleComponent } from './components/example.component' @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-root', template: ``, imports: [ExampleComponent], }) export class AppComponent {} ``` -------------------------------- ### Standalone App Setup with provideTanStackQuery Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/provideTanStackQuery.md Use this snippet to set up TanStack Query in a standalone Angular application. It requires importing `provideTanStackQuery` and `QueryClient` from the experimental package. ```typescript import { provideTanStackQuery, QueryClient, } from '@tanstack/angular-query-experimental' bootstrapApplication(AppComponent, { providers: [provideTanStackQuery(new QueryClient())], }) ``` -------------------------------- ### Infinite Query Setup in Angular Source: https://tanstack.com/query/v5/docs/framework/angular/guides/infinite-queries.md Configures an infinite query to fetch paginated project data, including initial parameters and next page logic. ```typescript import { Component, computed, inject } from '@angular/core' import { injectInfiniteQuery } from '@tanstack/angular-query-experimental' import { lastValueFrom } from 'rxjs' import { ProjectsService } from './projects-service' @Component({ selector: 'example', templateUrl: './example.component.html', }) export class Example { projectsService = inject(ProjectsService) query = injectInfiniteQuery(() => ({ queryKey: ['projects'], queryFn: async ({ pageParam }) => { return lastValueFrom(this.projectsService.getProjects(pageParam)) }, initialPageParam: 0, getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined, getNextPageParam: (lastPage) => lastPage.nextId ?? undefined, maxPages: 3, })) nextButtonDisabled = computed( () => !this.#hasNextPage() || this.#isFetchingNextPage(), ) nextButtonText = computed(() => this.#isFetchingNextPage() ? 'Loading more...' : this.#hasNextPage() ? 'Load newer' : 'Nothing more to load', ) #hasNextPage = this.query.hasNextPage #isFetchingNextPage = this.query.isFetchingNextPage } ``` -------------------------------- ### Using InjectionToken with provideTanStackQuery Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/provideTanStackQuery.md This advanced example shows how to provide a `QueryClient` using an `InjectionToken`. This allows TanStack Query to be excluded from the main bundle and included only in lazy-loaded modules. ```typescript export const MY_QUERY_CLIENT = new InjectionToken('', { factory: () => new QueryClient(), }) // In a lazy loaded route or lazy loaded component's providers array: providers: [provideTanStackQuery(MY_QUERY_CLIENT)] ``` -------------------------------- ### Bi-directional Infinite Query Setup Source: https://tanstack.com/query/v5/docs/framework/angular/guides/infinite-queries.md Configures an infinite query to support fetching both next and previous pages by defining `getNextPageParam` and `getPreviousPageParam`. ```typescript query = injectInfiniteQuery(() => ({ queryKey: ['projects'], queryFn: fetchProjects, getNextPageParam: (lastPage, pages) => lastPage.nextCursor, getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor, })) ``` -------------------------------- ### Angular Root Component Setup Source: https://tanstack.com/query/v5/docs/framework/angular/examples/auto-refetching This is the main application component in Angular. It imports and uses the AutoRefetchingExampleComponent to display the auto-refetching functionality. ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { AutoRefetchingExampleComponent } from './components/auto-refetching.component' @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-root', template: ``, imports: [AutoRefetchingExampleComponent], }) export class AppComponent {} ``` -------------------------------- ### Enabling Devtools with provideTanStackQuery Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/provideTanStackQuery.md Integrate developer tools into your TanStack Query setup by using the `withDevtools` option. This is typically enabled only in development mode. ```typescript import { provideTanStackQuery, withDevtools QueryClient, } from '@tanstack/angular-query-experimental' bootstrapApplication(AppComponent, { providers: [ provideTanStackQuery(new QueryClient(), withDevtools()) ] } ) ``` -------------------------------- ### Reactive Example Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/injectQuery.md Demonstrates how injectQuery works with Angular signals, automatically enabling and executing the query when a signal changes to a truthy value and disabling it when it becomes falsy. ```APIDOC ## Reactive Example ```ts class ServiceOrComponent { filter = signal('') todosQuery = injectQuery(() => ({ queryKey: ['todos', this.filter()], queryFn: () => fetchTodos(this.filter()), // Signals can be combined with expressions enabled: !!this.filter(), })) } ``` ``` -------------------------------- ### Define Query Options with queryOptions Source: https://tanstack.com/query/v5/docs/framework/angular/guides/query-options.md Use `queryOptions` to define query configurations, including `queryKey` and `queryFn`, for better organization and TypeScript support. This example shows how to create a service that returns query options for fetching a post. ```typescript import { queryOptions } from '@tanstack/angular-query-experimental' @Injectable({ providedIn: 'root', }) export class QueriesService { private http = inject(HttpClient) post(postId: number) { return queryOptions({ queryKey: ['post', postId], queryFn: () => { return lastValueFrom( this.http.get( `https://jsonplaceholder.typicode.com/posts/${postId}`, ), ) }, }) } } // usage: postId = input.required({ transform: numberAttribute, }) queries = inject(QueriesService) postQuery = injectQuery(() => this.queries.post(this.postId())) queryClient.prefetchQuery(this.queries.post(23)) queryClient.setQueryData(this.queries.post(42).queryKey, newPost) ``` -------------------------------- ### Configure TanStack Query with Lazy Devtools Source: https://tanstack.com/query/v5/docs/framework/angular/devtools.md This configuration example shows how to integrate the devtools into an Angular application using `provideTanStackQuery` and `withDevtools`. It demonstrates injecting a service to control `loadDevtools` and specifies the `deps` for the callback. ```typescript // ... // 👇 Note we import from the production sub-path to enable devtools lazy loading in production builds import { withDevtools } from '@tanstack/angular-query-experimental/devtools/production' export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(), provideTanStackQuery( new QueryClient(), withDevtools( (devToolsOptionsManager: DevtoolsOptionsManager) => ({ loadDevtools: devToolsOptionsManager.loadDevtools(), }), { // `deps` is used to inject and pass `DevtoolsOptionsManager` to the `withDevtools` callback. deps: [DevtoolsOptionsManager], }, ), ), ], } ``` -------------------------------- ### Basic Angular Component Setup Source: https://tanstack.com/query/v5/docs/framework/angular/examples/basic This component sets up the basic structure for an Angular application. It imports necessary modules and defines a signal for managing post IDs. Ensure `PostComponent` and `PostsComponent` are correctly defined and imported. ```typescript import { ChangeDetectionStrategy, Component, signal } from '@angular/core' import { PostComponent } from './components/post.component' import { PostsComponent } from './components/posts.component' @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'basic-example', templateUrl: './app.component.html', imports: [PostComponent, PostsComponent], }) export class BasicExampleComponent { readonly postId = signal(-1) } ``` -------------------------------- ### Angular Root Component Setup Source: https://tanstack.com/query/v5/docs/framework/angular/examples/query-options-from-a-service This is the main application component. It sets up the router outlet for navigation. Ensure this component is correctly configured in your Angular application. ```typescript import { Component } from '@angular/core' import { RouterOutlet } from '@angular/router' @Component({ selector: 'app-root', imports: [RouterOutlet], templateUrl: './app.component.html', }) export class AppComponent {} ``` -------------------------------- ### Use Placeholder Data from Cache Source: https://tanstack.com/query/v5/docs/framework/angular/guides/placeholder-query-data.md Provide placeholder data for a query by fetching it from the cache of another query. This example uses a preview version of a blog post from a 'blogPosts' query as placeholder data for an individual 'blogPost' query. ```typescript export class BlogPostComponent { postId = input.required() queryClient = inject(QueryClient) result = injectQuery(() => ({ queryKey: ['blogPost', this.postId()], queryFn: () => fetch(`/blogPosts/${this.postId()}`), placeholderData: () => { // Use the smaller/preview version of the blogPost from the 'blogPosts' // query as the placeholder data for this blogPost query return this.queryClient .getQueryData(['blogPosts']) ?.find((d) => d.id === this.postId()) }, })) } ``` -------------------------------- ### Using injectQuery for Dependent Queries Source: https://tanstack.com/query/v5/docs/framework/angular/guides/dependent-queries.md Use the `enabled` option to control when a query should execute. This example shows fetching user data first, then fetching projects based on the user's ID. ```typescript userQuery = injectQuery(() => ({ queryKey: ['user', email], queryFn: getUserByEmail, })) projectsQuery = injectQuery(() => ({ queryKey: ['projects', this.userQuery.data()?.id], queryFn: getProjectsByUser, // The query will not execute until the user id exists enabled: !!this.userQuery.data()?.id, })) ``` -------------------------------- ### Configure Global Retry Delay Source: https://tanstack.com/query/v5/docs/framework/angular/guides/query-retries.md Set a custom back-off delay for all queries using `retryDelay`. This example doubles the delay with each attempt, capped at 30 seconds. ```typescript // Configure for all queries import { QueryCache, QueryClient, QueryClientProvider, } from '@tanstack/angular-query-experimental' const queryClient = new QueryClient({ defaultOptions: { queries: { retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), }, }, }) bootstrapApplication(AppComponent, { providers: [provideTanStackQuery(queryClient)], }) ``` -------------------------------- ### App Component Setup for Optimistic Updates Source: https://tanstack.com/query/v5/docs/framework/angular/examples/optimistic-updates This Angular component sets up the root of the application, importing and rendering the OptimisticUpdatesComponent. It uses OnPush change detection for performance. ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { OptimisticUpdatesComponent } from './components/optimistic-updates.component' @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-root', template: ``, imports: [OptimisticUpdatesComponent], }) export class AppComponent {} ``` ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { OptimisticUpdatesComponent } from './components/optimistic-updates.component' @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-root', template: ``, imports: [OptimisticUpdatesComponent], }) export class AppComponent {} ``` -------------------------------- ### Manual Parallel Queries with injectQuery Source: https://tanstack.com/query/v5/docs/framework/angular/guides/parallel-queries.md Use multiple `injectQuery` functions side-by-side to execute queries in parallel when the number of queries is known and static. No special setup is required. ```typescript export class AppComponent { // The following queries will execute in parallel usersQuery = injectQuery(() => ({ queryKey: ['users'], queryFn: fetchUsers })) teamsQuery = injectQuery(() => ({ queryKey: ['teams'], queryFn: fetchTeams })) projectsQuery = injectQuery(() => ({ queryKey: ['projects'], queryFn: fetchProjects, })) } ``` -------------------------------- ### Define and Use Reusable Mutation Options Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/mutationOptions.md Use mutationOptions to create reusable mutation configurations. This example shows how to define an updatePost mutation in a service and then use it within a component. ```typescript export class QueriesService { private http = inject(HttpClient) private queryClient = inject(QueryClient) updatePost(id: number) { return mutationOptions({ mutationFn: (post: Post) => Promise.resolve(post), mutationKey: ["updatePost", id], onSuccess: (newPost) => { // ^? newPost: Post this.queryClient.setQueryData(["posts", id], newPost) }, }); } } class ComponentOrService { queries = inject(QueriesService) id = signal(0) mutation = injectMutation(() => this.queries.updatePost(this.id())) save() { this.mutation.mutate({ title: 'New Title' }) } } ``` -------------------------------- ### Custom Background Retry Strategy Source: https://tanstack.com/query/v5/docs/framework/angular/guides/query-retries.md Disable built-in retries and implement a custom refetch interval for continuous background retries. This example refetches more frequently when the query is in an error state. ```typescript const result = injectQuery({ queryKey: ['todos'], queryFn: fetchTodos, refetchInterval: (query) => { // Refetch more frequently when in error state return query.state.status === 'error' ? 5000 : 30000 }, refetchIntervalInBackground: true, retry: false, // Disable built-in retries }) ``` -------------------------------- ### Test a basic query with TestBed Source: https://tanstack.com/query/v5/docs/framework/angular/guides/testing.md Write unit tests for queries by using `TestBed.runInInjectionContext` and awaiting stability with `ApplicationRef.whenStable()`. Trigger effects with `TestBed.tick()` before asserting on the query's status and data. ```typescript const appRef = TestBed.inject(ApplicationRef) const query = TestBed.runInInjectionContext(() => injectQuery(() => ({ queryKey: ['greeting'], queryFn: () => 'Hello', })), ) TestBed.tick() // Trigger effect // Application is stable when queries are idle await appRef.whenStable() expect(query.status()).toBe('success') expect(query.data()).toBe('Hello') ``` -------------------------------- ### Check Number of Fetching Mutations Source: https://tanstack.com/query/v5/docs/framework/angular/guides/filters.md Use `isMutating` without filters to get the count of all mutations that are currently in a fetching state. ```typescript await queryClient.isMutating() ``` -------------------------------- ### infiniteQueryOptions() - DefinedInitialDataInfiniteOptions Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/infiniteQueryOptions.md This overload of `infiniteQueryOptions` is used when initial data is defined. It accepts `DefinedInitialDataInfiniteOptions` and returns a `CreateInfiniteQueryOptions` object. ```APIDOC ## Function: infiniteQueryOptions(options: DefinedInitialDataInfiniteOptions): CreateInfiniteQueryOptions & object & object ### Description Allows to share and re-use infinite query options in a type-safe way. The `queryKey` will be tagged with the type from `queryFn`. ### Type Parameters * `TQueryFnData`: The type of the data returned by the query function. * `TError`: The type of the error that may occur. * `TData`: The type of the data returned by the query (defaults to `InfiniteData`) * `TQueryKey`: The type of the query key (defaults to `readonly unknown[]`) * `TPageParam`: The type of the page parameter (defaults to `unknown`) ### Parameters * `options` (`DefinedInitialDataInfiniteOptions`): The infinite query options to tag with the type from `queryFn`. ### Returns * `CreateInfiniteQueryOptions & object & object`: The tagged infinite query options. ``` -------------------------------- ### Valid Query Function Configurations Source: https://tanstack.com/query/v5/docs/framework/angular/guides/query-functions.md Demonstrates various ways to configure query functions, including direct function return, async functions, and using query key parameters. ```typescript injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchAllTodos })) ``` ```typescript injectQuery(() => ({ queryKey: ['todos', todoId], queryFn: () => fetchTodoById(todoId) }) ``` ```typescript injectQuery(() => ({ queryKey: ['todos', todoId], queryFn: async () => { const data = await fetchTodoById(todoId) return data }, })) ``` ```typescript injectQuery(() => ({ queryKey: ['todos', todoId], queryFn: ({ queryKey }) => fetchTodoById(queryKey[1]), })) ``` -------------------------------- ### Basic Paginated Query Source: https://tanstack.com/query/v5/docs/framework/angular/guides/paginated-queries.md A simple example of a paginated query where the page number is part of the query key. This can lead to UI jumps between states. ```typescript const result = injectQuery(() => ({ queryKey: ['projects', page()], queryFn: fetchProjects, })) ``` -------------------------------- ### Provide TanStack Query Client in Angular App Source: https://tanstack.com/query/v5/docs/framework/angular/quick-start.md Configure TanStack Query by providing the QueryClient to your Angular application. This setup is for standalone applications. ```ts import { provideHttpClient } from '@angular/common/http' import { provideTanStackQuery, QueryClient, } from '@tanstack/angular-query-experimental' bootstrapApplication(AppComponent, { providers: [provideHttpClient(), provideTanStackQuery(new QueryClient())], }) ``` -------------------------------- ### Provide Initial Data with `initialData` Source: https://tanstack.com/query/v5/docs/framework/angular/guides/initial-query-data.md Use the `initialData` option to prepopulate a query's cache if data is already available. This skips the initial loading state. ```typescript result = injectQuery(() => ({ queryKey: ['todos'], queryFn: () => fetch('/todos'), initialData: initialTodos, })) ``` -------------------------------- ### Type Inference with HttpClient Source: https://tanstack.com/query/v5/docs/framework/angular/typescript.md Shows type inference when fetching data using HttpClient, specifying the expected return type for the `get` method. ```typescript @Component({ template: `@let data = query.data();`, // ^? data: Group[] | undefined }) class MyComponent { http = inject(HttpClient) query = injectQuery(() => ({ queryKey: ['groups'], queryFn: () => lastValueFrom(this.http.get('/groups')), })) } ``` -------------------------------- ### Invalidate Queries by Prefix Source: https://tanstack.com/query/v5/docs/framework/angular/guides/query-invalidation.md Invalidate all queries whose keys start with a specific prefix. This is useful for clearing related data, such as all 'todos' entries. ```typescript queryClient.invalidateQueries({ queryKey: ['todos'] }) ``` -------------------------------- ### Test a component using injectQuery Source: https://tanstack.com/query/v5/docs/framework/angular/guides/testing.md For component testing, bootstrap the component using `TestBed.createComponent` and then await `fixture.whenStable()` to ensure any queries within the component have settled before making assertions. ```typescript const fixture = TestBed.createComponent(ExampleComponent) await fixture.whenStable() expect(fixture.componentInstance.query.data()).toEqual({ value: 42 }) ``` -------------------------------- ### infiniteQueryOptions() - UndefinedInitialDataInfiniteOptions Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/infiniteQueryOptions.md This overload of `infiniteQueryOptions` is used when initial data is undefined. It accepts `UndefinedInitialDataInfiniteOptions` and returns a `CreateInfiniteQueryOptions` object. ```APIDOC ## Function: infiniteQueryOptions(options: UndefinedInitialDataInfiniteOptions): CreateInfiniteQueryOptions & object & object ### Description Allows to share and re-use infinite query options in a type-safe way. The `queryKey` will be tagged with the type from `queryFn`. ### Type Parameters * `TQueryFnData`: The type of the data returned by the query function. * `TError`: The type of the error that may occur. * `TData`: The type of the data returned by the query (defaults to `InfiniteData`) * `TQueryKey`: The type of the query key (defaults to `readonly unknown[]`) * `TPageParam`: The type of the page parameter (defaults to `unknown`) ### Parameters * `options` (`UndefinedInitialDataInfiniteOptions`): The infinite query options to tag with the type from `queryFn`. ### Returns * `CreateInfiniteQueryOptions & object & object`: The tagged infinite query options. ``` -------------------------------- ### Type Narrowing for Axios Errors Source: https://tanstack.com/query/v5/docs/framework/angular/typescript.md Provides an example of type narrowing for the error field when dealing with specific error types like `AxiosError` using `axios.isAxiosError`. ```typescript import axios from 'axios' query = injectQuery(() => ({ queryKey: ['groups'], queryFn: fetchGroups })) computed(() => { const error = query.error() // ^? error: Error | null if (axios.isAxiosError(error)) { error // ^? const error: AxiosError } }) ``` -------------------------------- ### provideQueryClient() Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/provideQueryClient.md Provides a QueryClient instance. This is typically used internally by provideTanStackQuery, but can be used directly to supply a specific QueryClient for a sub-application or for testing. ```APIDOC ## Function: provideQueryClient() ### Signature ```ts function provideQueryClient(queryClient: QueryClient | InjectionToken): Provider; ``` ### Description Provides a `QueryClient` instance. This function is usually called internally by `provideTanStackQuery` to set up TanStack Query for the entire application. However, you can use `provideQueryClient` directly to provide a different `QueryClient` instance for a specific part of the application or for unit testing. ### Parameters #### queryClient - **queryClient** (`QueryClient` | `InjectionToken`) - A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`. ### Returns - **Provider** - A provider object that can be used to provide the `QueryClient` instance. ``` -------------------------------- ### provideTanStackQuery() Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/provideTanStackQuery.md Sets up providers necessary to enable TanStack Query functionality for Angular applications. Allows to configure a `QueryClient` and optional features such as developer tools. ```APIDOC ## Function: provideTanStackQuery() ### Signature ```ts function provideTanStackQuery(queryClient, ...features): Provider[]; ``` ### Description Sets up providers necessary to enable TanStack Query functionality for Angular applications. Allows to configure a `QueryClient` and optional features such as developer tools. ### Parameters #### queryClient - **Type**: `QueryClient` | `InjectionToken` - **Description**: A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`. #### features - **Type**: `QueryFeatures[]` - **Description**: Optional features to configure additional Query functionality. ### Returns - **Type**: `Provider[]` - **Description**: A set of providers to set up TanStack Query. ### Examples **Standalone Application** ```ts import { provideTanStackQuery, QueryClient, } from '@tanstack/angular-query-experimental' bootstrapApplication(AppComponent, { providers: [provideTanStackQuery(new QueryClient())], }) ``` **NgModule-based Application** ```ts import { provideTanStackQuery, QueryClient, } from '@tanstack/angular-query-experimental' @NgModule({ declarations: [AppComponent], imports: [BrowserModule], providers: [provideTanStackQuery(new QueryClient())], bootstrap: [AppComponent], }) export class AppModule {} ``` **With Devtools** ```ts import { provideTanStackQuery, withDevtools, QueryClient, } from '@tanstack/angular-query-experimental' bootstrapApplication(AppComponent, { providers: [ provideTanStackQuery(new QueryClient(), withDevtools()) ] } ) ``` **Using an InjectionToken** ```ts export const MY_QUERY_CLIENT = new InjectionToken('', { factory: () => new QueryClient(), }) // In a lazy loaded route or lazy loaded component's providers array: providers: [provideTanStackQuery(MY_QUERY_CLIENT)] ``` ### See Also - https://tanstack.com/query/v5/docs/framework/angular/quick-start - withDevtools ``` -------------------------------- ### Angular Root Component Setup Source: https://tanstack.com/query/v5/docs/framework/angular/examples/router This component is the root of the Angular application and includes the RouterOutlet directive to render routed components. It uses OnPush change detection strategy. ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core' import { RouterOutlet } from '@angular/router' @Component({ selector: 'app-root', changeDetection: ChangeDetectionStrategy.OnPush, imports: [RouterOutlet], templateUrl: './app.component.html', }) export class AppComponent {} ``` -------------------------------- ### Initial Data Configuration Source: https://tanstack.com/query/v5/docs/framework/angular/reference/type-aliases/DefinedInitialDataOptions.md Specifies how to provide initial data for a query. It can be a non-undefined value or a function that returns a non-undefined value. ```typescript initialData: | NonUndefinedGuard | () => NonUndefinedGuard; ``` -------------------------------- ### CreateBaseQueryOptions Interface Source: https://tanstack.com/query/v5/docs/framework/angular/reference/interfaces/CreateBaseQueryOptions.md This interface defines the base options for creating queries, extending `QueryObserverOptions` and providing type parameters for query data, errors, and keys. ```APIDOC ## Interface: CreateBaseQueryOptions ### Description This interface represents the base options for configuring queries. It extends `QueryObserverOptions` and allows for generic type definitions for query function data, errors, and query keys. ### Type Parameters - **TQueryFnData** (`unknown`): The type of data returned by the query function. - **TError** (`DefaultError`): The type of error that may occur during the query. - **TData** (`TQueryFnData`): The type of the data returned by the query observer. - **TQueryData** (`TQueryFnData`): The type of the data stored in the query cache. - **TQueryKey** (*extends* `QueryKey` = `QueryKey`): The type of the query key, which uniquely identifies the query. ``` -------------------------------- ### Using axios with AbortSignal Source: https://tanstack.com/query/v5/docs/framework/angular/guides/query-cancellation.md Illustrates how to integrate AbortSignal with the `axios` library for request cancellation. The signal is passed directly in the `axios.get` configuration. ```ts import axios from 'axios' const query = injectQuery(() => ({ queryKey: ['todos'], queryFn: ({ signal }) => axios.get('/todos', { // Pass the signal to `axios` signal, }), })) ``` -------------------------------- ### Configure QueryClient and provide TanStack Query Source: https://tanstack.com/query/v5/docs/framework/angular/guides/testing.md Set up a `QueryClient` with custom default options and provide it to your Angular application using `provideTanStackQuery`. Ensure `withDevtools` is not included in test providers to avoid slow tests. Call `queryClient.clear()` in `afterEach` to prevent data leakage between tests. ```typescript const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, // ✅ faster failure tests }, }, }) TestBed.configureTestingModule({ providers: [provideTanStackQuery(queryClient)], }) ``` -------------------------------- ### Resetting Mutation State Source: https://tanstack.com/query/v5/docs/framework/angular/guides/mutations.md This example demonstrates how to reset a mutation's state, clearing any `error` or `data`. The `mutation.reset()` function is called when an error message is clicked, allowing the user to clear the error and potentially retry the operation. ```typescript @Component({ selector: 'todo-item', imports: [ReactiveFormsModule], template: `
@if (mutation.error()) {
{{ mutation.error() }}
}
`, }) export class TodosComponent { mutation = injectMutation(() => ({ mutationFn: createTodo, })) fb = inject(NonNullableFormBuilder) todoForm = this.fb.group({ title: this.fb.control('', { validators: [Validators.required], }), }) title = toSignal(this.todoForm.controls.title.valueChanges, { initialValue: '', }) onCreateTodo = () => { this.mutation.mutate(this.title()) } } ``` -------------------------------- ### Manual Query Cancellation with QueryClient Source: https://tanstack.com/query/v5/docs/framework/angular/guides/query-cancellation.md Demonstrates how to manually cancel a query using `queryClient.cancelQueries`. This is useful for implementing user-initiated cancellation, such as stopping a long-running request via a button click. ```ts @Component({ template: ``, }) export class TodosComponent { query = injectQuery(() => ({ queryKey: ['todos'], queryFn: async ({ signal }) => { const resp = await fetch('/todos', { signal }) return resp.json() }, })) queryClient = inject(QueryClient) onCancel() { this.queryClient.cancelQueries(['todos']) } } ``` -------------------------------- ### Disable Query with enabled: false Source: https://tanstack.com/query/v5/docs/framework/angular/guides/disabling-queries.md Use `enabled: false` to prevent a query from automatically fetching on mount or refetching in the background. The query will retain cached data if available, otherwise it starts in a pending state. Manual refetching is still possible. ```typescript import { injectQuery } from '@tanstack/query-angular'; @Component({ selector: 'todos', template: `
@if (query.data()) {
    @for (todo of query.data(); track todo.id) {
  • {{ todo.title }}
  • }
} @else { @if (query.isError()) { Error: {{ query.error().message }} } @else if (query.isLoading()) { Loading... } @else if (!query.isLoading() && !query.isError()) { Not ready ... } }
{{ query.isLoading() ? 'Fetching...' : '' }}
`, }) export class TodosComponent { query = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList, enabled: false, })) } ``` -------------------------------- ### Handle Query States with Switch Statement Source: https://tanstack.com/query/v5/docs/framework/angular/guides/queries.md Alternatively, use a switch statement on the `status` property to manage different query states and render the appropriate UI. ```html @switch (todos.status()) { @case ('pending') { Loading... } @case ('error') { Error: {{ todos.error()?.message }} } @default {
    @for (todo of todos.data(); track todo.id) {
  • {{ todo.title }}
  • }
} } ``` -------------------------------- ### infiniteQueryOptions() - UnusedSkipTokenInfiniteOptions Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/infiniteQueryOptions.md This overload of `infiniteQueryOptions` is used when skip tokens are involved. It accepts `UnusedSkipTokenInfiniteOptions` and returns an `OmitKeyof` version of `CreateInfiniteQueryOptions`. ```APIDOC ## Function: infiniteQueryOptions(options: UnusedSkipTokenInfiniteOptions): OmitKeyof, "queryFn"> & object & object ### Description Allows to share and re-use infinite query options in a type-safe way. The `queryKey` will be tagged with the type from `queryFn`. ### Type Parameters * `TQueryFnData`: The type of the data returned by the query function. * `TError`: The type of the error that may occur. * `TData`: The type of the data returned by the query (defaults to `InfiniteData`) * `TQueryKey`: The type of the query key (defaults to `readonly unknown[]`) * `TPageParam`: The type of the page parameter (defaults to `unknown`) ### Parameters * `options` (`UnusedSkipTokenInfiniteOptions`): The infinite query options to tag with the type from `queryFn`. ### Returns * `OmitKeyof, "queryFn"> & object & object`: The tagged infinite query options. ``` -------------------------------- ### Define and Use Mutations with Persistence Source: https://tanstack.com/query/v5/docs/framework/angular/guides/mutations.md Configure default mutation behaviors like `mutationFn`, `onMutate`, `onSuccess`, `onError`, and `retry`. This setup allows for optimistic updates and error handling. Mutations can be dehydrated and hydrated to persist state across application sessions, and `resumePausedMutations` can be called to resume any paused mutations. ```typescript const queryClient = new QueryClient() // Define the "addTodo" mutation queryClient.setMutationDefaults(['addTodo'], { mutationFn: addTodo, onMutate: async (variables, context) => { // Cancel current queries for the todos list await context.client.cancelQueries({ queryKey: ['todos'] }) // Create optimistic todo const optimisticTodo = { id: uuid(), title: variables.title } // Add optimistic todo to todos list context.client.setQueryData(['todos'], (old) => [...old, optimisticTodo]) // Return result with the optimistic todo return { optimisticTodo } }, onSuccess: (result, variables, onMutateResult, context) => { // Replace optimistic todo in the todos list with the result context.client.setQueryData(['todos'], (old) => old.map((todo) => todo.id === onMutateResult.optimisticTodo.id ? result : todo, ), ) }, onError: (error, variables, onMutateResult, context) => { // Remove optimistic todo from the todos list context.client.setQueryData(['todos'], (old) => old.filter((todo) => todo.id !== onMutateResult.optimisticTodo.id), ) }, retry: 3, }) class someComponent { // Start mutation in some component: mutation = injectMutation(() => ({ mutationKey: ['addTodo'] })) someMethod() { mutation.mutate({ title: 'title' }) } } // If the mutation has been paused because the device is for example offline, // Then the paused mutation can be dehydrated when the application quits: const state = dehydrate(queryClient) // The mutation can then be hydrated again when the application is started: hydrate(queryClient, state) // Resume the paused mutations: queryClient.resumePausedMutations() ``` -------------------------------- ### injectInfiniteQuery (CreateInfiniteQueryResult - CreateInfiniteQueryOptions) Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/injectInfiniteQuery.md Injects an infinite query and returns a CreateInfiniteQueryResult. This version accepts CreateInfiniteQueryOptions. ```APIDOC ## Function: injectInfiniteQuery() Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a unique key. Infinite queries can additively "load more" data onto an existing set of data or "infinite scroll". ### Type Parameters #### TQueryFnData `TQueryFnData` #### TError `TError` = `Error` #### TData `TData` = `InfiniteData`\<`TQueryFnData`, `unknown`\> #### TQueryKey `TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[] #### TPageParam `TPageParam` = `unknown` ### Parameters #### injectInfiniteQueryFn () => [`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\> A function that returns infinite query options. #### options? [`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md) Additional configuration. ### Returns [`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\> The infinite query result. ``` -------------------------------- ### Reactive Query Injection with Signals Source: https://tanstack.com/query/v5/docs/framework/angular/reference/functions/injectQuery.md Demonstrates how to use signals to control query reactivity. The query is automatically enabled when the filter signal is truthy and disabled when it's falsy. ```typescript class ServiceOrComponent { filter = signal('') todosQuery = injectQuery(() => ({ queryKey: ['todos', this.filter()], queryFn: () => fetchTodos(this.filter()), // Signals can be combined with expressions enabled: !!this.filter(), })) } ``` -------------------------------- ### provideIsRestoring Source: https://tanstack.com/query/v5/docs/framework/angular/reference/index.md Provides a service to track and manage the state of query client restoration. This is typically used in conjunction with state persistence. ```APIDOC ## provideIsRestoring ### Description Provides a service to track and manage the state of query client restoration. ### Signature ```typescript function provideIsRestoring(): EnvironmentProviders ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript // Example usage in app.config.ts (Angular 16+) import { ApplicationConfig } from '@angular/core'; import { provideRouter } from '@angular/router'; import { provideAngularQuery, provideIsRestoring } from '@tanstack/angular-query-experimental'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ provideRouter(routes), provideAngularQuery(), provideIsRestoring(), // Add this line // other providers... ] }; ``` ### Response #### Success Response (200) Returns `EnvironmentProviders` that configure the restoration tracking service. #### Response Example ```typescript // Returns an EnvironmentProviders object ``` ``` -------------------------------- ### queryOptions Source: https://tanstack.com/query/v5/docs/framework/angular/reference/index.md Creates options for a query. This is a helper function to configure query behavior. ```APIDOC ## queryOptions ### Description Creates options for a query. ### Signature ```typescript function queryOptions( options: CreateQueryOptions ): CreateQueryOptions ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript // Example usage import { queryOptions } from '@tanstack/angular-query-experimental'; const myQueryOptions = queryOptions({ queryKey: ['todos'], queryFn: async () => { const response = await fetch('/api/todos'); return response.json(); }, staleTime: 1000 * 60 * 5 // 5 minutes }); // This object can then be passed to injectQuery // const query = injectQuery(() => myQueryOptions); ``` ### Response #### Success Response (200) Returns the query options object, potentially with default values applied. #### Response Example ```json { "queryKey": ["todos"], "queryFn": "async () => { ... }", "staleTime": 300000 } ``` ``` -------------------------------- ### Using fetch with AbortSignal Source: https://tanstack.com/query/v5/docs/framework/angular/guides/query-cancellation.md Shows how to pass an AbortSignal to the native `fetch` API within a query function. This allows `fetch` requests to be cancelled when the query is no longer needed. ```ts query = injectQuery(() => ({ queryKey: ['todos'], queryFn: async ({ signal }) => { const todosResponse = await fetch('/todos', { // Pass the signal to one fetch signal, }) const todos = await todosResponse.json() const todoDetails = todos.map(async ({ details }) => { const response = await fetch(details, { // Or pass it to several signal, }) return response.json() }) return Promise.all(todoDetails) }, })) ``` -------------------------------- ### Using onSettled for Error Handling in Mutations Source: https://tanstack.com/query/v5/docs/framework/angular/guides/optimistic-updates.md Demonstrates using the `onSettled` callback to handle both success and error scenarios, including custom error logic. ```typescript injectMutation({ mutationFn: updateTodo, // ... onSettled: (newTodo, error, variables, onMutateResult, context) => { if (error) { // do something } }, }) ``` -------------------------------- ### Provide Placeholder Data to a Query Source: https://tanstack.com/query/v5/docs/framework/angular/guides/placeholder-query-data.md Use the `placeholderData` option to provide initial data for a query. This prevents the query from entering a pending state if data is available, even if it's just placeholder data. The `isPlaceholderData` flag will be true on the query result. ```typescript class TodosComponent { result = injectQuery(() => ({ queryKey: ['todos'], queryFn: () => fetch('/todos'), placeholderData: placeholderTodos, })) } ```