What is Angular Query?

Daniel Glejzner - Feb 3 - - Dev Community

Short breakdown πŸ‘‡

Angular Query is used for syncing server data with client applications.

  • Without any unneeded abstractions.

Ideal for

  • grids

  • tables

  • listings

  • etc…

We have 2 packages to look at

  1. ngneat/query

  2. tanstack/angular-query-experimental

ngneat is unofficial adapter

TanStack one is official

  • developed by @Arnoud_dv @tan_stack

  • for now supports only Signals

  • RxJS support planned for the future

Both are using TanStack Query Core.

🟨 Core Concepts 🟨

1. Queries

  • Declaratively manage data fetching.

  • Letting Angular Query handle the timing and specifics of server communication.

2. Mutations

  • Handle data modification

  • Integrating queries for a consistent data management

🧹 Cache & Cleanup 🧹

1. Cache Management

  • Data maintenance and retrieval is handled by Query Client & Query Cache.

2. Query Keys

  • A system for identifying and managing data dependencies across components.

3. SWR

  • Ensures data freshness by smartly revalidating data behind the scenes without sacrificing performance.

πŸ’» Significant DX improvements πŸ’»

  • Reduced boilerplate Out of the box

  • Intelligent caching and data management strategies

  • Giant performance boost in writing async code

  • Pairs fantastic with component state management libraries

Basic usage with ngneat/query:

Service usage:

    import { injectQuery } from '@ngneat/query';

    @Injectable({ providedIn: 'root' })
    export class TodosService {
      #http = inject(HttpClient);
      #query = injectQuery();

      getTodos() {
        return this.#query({
          queryKey: ['todos'] as const,
          queryFn: () => {
            return this.http.get<Todo[]>(
              'https://jsonplaceholder.typicode.com/todos',
            );
          },
        });
      }
    }
Enter fullscreen mode Exit fullscreen mode

Component usage with Observables:


    @Component({
      standalone: true,
      template: `
        @if (todos.result$ | async; as result) {
          @if (result.isLoading) {
            <p>Loading</p>
          }
          @if (result.isSuccess) {
            <p>{{ result.data[0].title }}</p>
          }
          @if (result.isError) {
            <p>Error</p>
          }
        }
      `,
    })
    export class TodosPageComponent {
      todos = inject(TodosService).getTodos();
    }
Enter fullscreen mode Exit fullscreen mode

Component usage with Signals:


    @Component({
      standalone: true,
      template: `
        @if (todos().isLoading) {
          Loading
        }
        @if (todos().data; as data) {
          <p>{{ data[0].title }}</p>
        }
        @if (todos().isError) {
          <p>Error</p>
        }
      `,
    })
    export class TodosPageComponent {
      todos = inject(TodosService).getTodos().result;
    }
Enter fullscreen mode Exit fullscreen mode

Docs:

ngneat: https://github.com/ngneat/query

TanStack: https://tanstack.com/query/latest/docs/framework/angular/overview

Follow me on X for more: https://twitter.com/DanielGlejzner

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .