Angular Query
Start by providing an OpenAPI specification and an Orval config file. To use Angular Query, define the client in the Orval config to be angular-query.
Example with Angular Query
import { defineConfig } from 'orval';export default defineConfig({petstore: {output: {mode: 'tags-split',target: 'src/petstore.ts',schemas: 'src/model',client: 'angular-query',httpClient: 'angular',mock: true,},input: {target: './petstore.yaml',},},});
Navigate to the Orval config reference to see all available options.
The Angular Query mode will generate an implementation file with one injectable query function per path in the OpenAPI Specification. By default, Orval uses Angular's native HttpClient via inject(HttpClient) for HTTP requests.
For example, this Swagger specification will generate the following:
// Base operation functionexport const showPetById = (http: HttpClient,petId: string,options?: { signal?: AbortSignal | null },): Promise<Pet> => {const url = `/pets/${petId}`;const request$ = http.get<Pet>(url);if (options?.signal) {return lastValueFrom(request$.pipe(takeUntil(fromEvent(options.signal, 'abort'))),);}return lastValueFrom(request$);};// Query key factoryexport const getShowPetByIdQueryKey = (petId?: string) => {return [`/pets/${petId}`] as const;};// Query options factoryexport const getShowPetByIdQueryOptions = <TData = Awaited<ReturnType<typeof showPetById>>,TError = unknown,>(http: HttpClient,petId: string,options?: {query?: Partial<CreateQueryOptions<Awaited<ReturnType<typeof showPetById>>, TError, TData>>;fetch?: RequestInit;},) => {const { query: queryOptions, fetch: fetchOptions } = options ?? {};const queryKey = queryOptions?.queryKey ?? getShowPetByIdQueryKey(petId);const queryFn: QueryFunction<Awaited<ReturnType<typeof showPetById>>> = ({signal,}) => showPetById(http, petId, { signal, ...fetchOptions });return {queryKey,queryFn,enabled: !!petId,...queryOptions,} as CreateQueryOptions<Awaited<ReturnType<typeof showPetById>>,TError,TData>;};// Injectable query functionexport function injectShowPetById<TData = Awaited<ReturnType<typeof showPetById>>,TError = unknown,>(petId: string | (() => string),options?:| {query?: Partial<CreateQueryOptions<Awaited<ReturnType<typeof showPetById>>,TError,TData>>;fetch?: RequestInit;}| (() => {query?: Partial<CreateQueryOptions<Awaited<ReturnType<typeof showPetById>>,TError,TData>>;fetch?: RequestInit;}),): CreateQueryResult<TData, TError> {const http = inject(HttpClient);const query = injectQuery(() => {const _petId = typeof petId === 'function' ? petId() : petId;const _options = typeof options === 'function' ? options() : options;return getShowPetByIdQueryOptions(http, _petId, _options);}) as CreateQueryResult<TData, TError>;return query;}
Signal Reactivity
The generated inject* functions support Angular signals out of the box. Parameters can be passed as getter functions, enabling reactive query updates when signals change:
@Component({...})export class PetDetailComponent {// Signal-based parameterpetId = signal('1');// Query automatically re-executes when petId() changespet = injectShowPetById(() => this.petId());// Also works with options for dynamic enabled/disabledconditionalPet = injectShowPetById(() => this.petId(),() => ({query: { enabled: this.isEnabled() },}),);}
This pattern works for all parameters including query params and options.
Mutations
For POST, PUT, PATCH, and DELETE operations, Orval generates mutation functions:
// Mutation options factoryexport const getCreatePetsMutationOptions = <TError = Error, TContext = unknown>(http: HttpClient,queryClient: QueryClient,options?: {mutation?: CreateMutationOptions<...>;fetch?: RequestInit;},) => { ... };// Injectable mutation functionexport const injectCreatePets = <TError = Error, TContext = unknown>(options?: {...}): CreateMutationResult<...> => {const http = inject(HttpClient);const queryClient = inject(QueryClient);// ...return injectMutation(() => mutationOptions);};
Usage:
@Component({...})export class CreatePetComponent {createPet = injectCreatePets();onSubmit(pet: CreatePetsBody) {this.createPet.mutate({ data: pet });}}
Query Invalidation
When useInvalidate: true is set, Orval generates helper functions to invalidate queries:
export const invalidateShowPetById = async (queryClient: QueryClient,petId: string,options?: InvalidateOptions,): Promise<QueryClient> => {await queryClient.invalidateQueries({ queryKey: getShowPetByIdQueryKey(petId) },options,);return queryClient;};
Automatic Mutation Invalidation (Angular Query Only)
The Angular Query client supports declarative, automatic query invalidation when mutations succeed via the mutationInvalidates config:
import { defineConfig } from 'orval';export default defineConfig({petstore: {output: {client: 'angular-query',override: {query: {useInvalidate: true,mutationInvalidates: [{onMutations: ['createPets'],invalidates: ['listPets'],},{onMutations: ['deletePet', 'updatePet', 'patchPet'],invalidates: ['listPets',{ query: 'showPetById', params: ['petId'] },],},],},},},// ...},});
This generates an onSuccess handler in the mutation options:
const onSuccess = (data, variables, onMutateResult, context) => {queryClient.invalidateQueries({ queryKey: getListPetsQueryKey() });queryClient.invalidateQueries({queryKey: getShowPetByIdQueryKey(variables.petId),});mutationOptions?.onSuccess?.(data, variables, onMutateResult, context);};
Param-based invalidation: With { query: 'showPetById', params: ['petId'] }, when deletePet({ petId: '123' }) succeeds, only the query for pet 123 is invalidated—not all showPetById queries.
Usage: To get automatic invalidation, use the generated inject* mutation functions:
@Component({template: `<ul>@for (pet of pets.data(); track pet.id) {<li>{{ pet.name }}<button (click)="onDelete(pet.id)">Delete</button></li>}</ul>`,})export class PetListComponent {// Query - will be automatically invalidated after mutationspets = injectListPets();// Mutation - automatic invalidation is built into the generated optionsdeletePet = injectDeletePet();onDelete(petId: string) {// After success, listPets and showPetById(petId) are automatically invalidatedthis.deletePet.mutate({ petId });}}
How to Use Other Queries
Given the following configuration, Orval will generate query and infinite query functions with a nextId query parameter. It is also possible to override the config for every query with the options field.
import { defineConfig } from 'orval';export default defineConfig({petstore: {output: {...override: {query: {useQuery: true,useInfinite: true,useInfiniteQueryParam: 'nextId',options: {staleTime: 10000,},},},},...},});
If needed, it is also possible to override the query options for a single operation or tag:
import { defineConfig } from 'orval';export default defineConfig({petstore: {output: {...override: {operations: {listPets: {query: {...},}},},}...},});
Go here for a full example