Skip to content

Commit 46034aa

Browse files
arnoud-dveneajahonartcTomasz Ducinducin
authored
feat: experimental angular query adapter (#6195)
* feat(angular-query): add Angular Query * feat(angular-query): integration test * fix(angular-query): PR feedback on QueryClientService injection * fix(angular-query): PR feedback * chore(angular-query): update unit tests * feat(angular-query): custom inject functions * feat(angular-query): docs * fix(angular-query): replace React context mention with Angular injector * fix(angular-query): re-add missing angular-query-experimental package config * feat: updated angular version * feat: code improvements, DX improvements, fixed small doc example to use http client, * Update docs/angular/overview.md * version fixes * feat: use proxy object to create single signals (computed) for query fields instead of query itself being a signal and improved types * fix: docs * Update packages/angular-query-experimental/src/query-proxy.ts Co-authored-by: Chau Tran <nartc7789@gmail.com> * Update packages/angular-query-experimental/src/query-proxy.ts Co-authored-by: Chau Tran <nartc7789@gmail.com> * fix: add missing import * revert: use helper method for injectQueryClient * Add Angular-CLI apps for testing * fix: useValue instead of useFactory * fix(angular-query): examples * chore(angular-query): remove build script from angular 17 integration * fix(angular-query): add sandbox config * build working for angular-query-devtools-experimental * fix(angular-query): improve development workflow * fix(angular-query): downgrade vitest * fix(angular-query): eslint and unit test typing fix * fix(angular-query): test:ci fixes * fix(angular-query): relative workspace path to build dir * fix(angular-query): configure workspaces for top directories only * chore(angular-query): remove dead code found by Knip --------- Co-authored-by: Enea Jahollari <jahollarienea14@gmail.com> Co-authored-by: Chau Tran <nartc7789@gmail.com> Co-authored-by: Tomasz Ducin <tomasz@ducin.it> Co-authored-by: Tomasz Ducin <tomasz.ducin@gmail.com> Co-authored-by: Dominik Dorfmeister <office@dorfmeister.cc>
1 parent af0ff9a commit 46034aa

117 files changed

Lines changed: 7188 additions & 773 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.codesandbox/ci.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
"installCommand": "install:csb",
33
"buildCommand": "build:all",
44
"sandboxes": [
5+
"/examples/angular/basic",
56
"/examples/react/basic-typescript",
67
"/examples/solid/basic-typescript",
78
"/examples/svelte/basic",
89
"/examples/vue/basic"
910
],
10-
"packages": ["packages/**"],
11+
"packages": ["packages/**", "!packages/angular*", "packages/angular-query-devtools-experimental/build", "packages/angular-query-experimental/build"],
1112
"node": "18"
1213
}

‎docs/angular/devtools.md‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
id: devtools
3+
title: Devtools
4+
---
5+
6+
## Install and Import the Devtools
7+
8+
The devtools are a separate package that you need to install:
9+
10+
```bash
11+
$ npm i @tanstack/angular-query-devtools-experimental
12+
# or
13+
$ pnpm add @tanstack/angular-query-devtools-experimental
14+
# or
15+
$ yarn add @tanstack/angular-query-devtools-experimental
16+
```
17+
18+
You can import the devtools like this:
19+
20+
```typescript
21+
import { AngularQueryDevtools } from '@tanstack/angular-query-devtools-experimental'
22+
```
23+
24+
## Floating Mode
25+
26+
Floating Mode will mount the devtools as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads.
27+
28+
Place the following code as high in your Angular app as you can. The closer it is to the root of the page, the better it will work!
29+
30+
```typescript
31+
import { AngularQueryDevtoolsComponent } from '@tanstack/angular-query-devtools-experimental'
32+
import { Component } from '@angular/core';
33+
34+
@Component({
35+
selector: 'app-root',
36+
standalone: true,
37+
imports: [AngularQueryDevtoolsComponent],
38+
template: `
39+
<angular-query-devtools initialIsOpen />
40+
`,
41+
})
42+
```
43+
44+
### Options
45+
46+
- `initialIsOpen: Boolean`
47+
- Set this `true` if you want the dev tools to default to being open
48+
- `buttonPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right"`
49+
- Defaults to `bottom-left`
50+
- The position of the TanStack logo to open and close the devtools panel
51+
- `position?: "top" | "bottom" | "left" | "right"`
52+
- Defaults to `bottom`
53+
- The position of the Angular Query devtools panel
54+
- `client?: QueryClient`,
55+
- Use this to use a custom QueryClient. Otherwise, the QueryClient provided through provideAngularQuery() will be injected.

‎docs/angular/installation.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
id: installation
3+
title: Installation
4+
---
5+
6+
> VERY IMPORTANT: This library is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Use at your own risk. If you choose to rely on this in production in an experimental stage, please lock your version to a patch-level version to avoid unexpected breakages.
7+
8+
### NPM
9+
10+
Angular Query is compatible with Angular v16+.
11+
12+
```bash
13+
$ npm i @tanstack/angular-query-experimental
14+
# or
15+
$ pnpm add @tanstack/angular-query-experimental
16+
# or
17+
$ yarn add @tanstack/angular-query-experimental
18+
```
19+
20+
> Wanna give it a spin before you download? Try out the [simple](../examples/angular/simple) or [basic](../examples/angular/basic) examples!

‎docs/angular/overview.md‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
id: overview
3+
title: Overview
4+
---
5+
6+
> VERY IMPORTANT: This library is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Use at your own risk. If you choose to rely on this in production in an experimental stage, please lock your version to a patch-level version to avoid unexpected breakages.
7+
8+
The `@tanstack/angular-query-experimental` package offers a 1st-class API for using TanStack Query via Angular.
9+
10+
## Feedback very welcome
11+
We are in the process of getting to a stable API for Angular Query. If you have any feedback, please contact us at the [TanStack Discord](https://tlinz.com/discord) server or [visit this discussion](https://github.com/TanStack/query/discussions/6293) on Github.
12+
13+
## Versions of Angular supported
14+
The adapter works with signals, which means it only supports Angular 16+
15+
16+
## Example
17+
18+
```typescript
19+
import { AngularQueryDevtoolsComponent } from '@tanstack/angular-query-devtools-experimental'
20+
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
21+
import { HttpClient } from '@angular/common/http'
22+
import { CommonModule } from '@angular/common'
23+
import { injectQuery } from '@tanstack/angular-query-experimental'
24+
import { lastValueFrom } from 'rxjs'
25+
26+
type Response = {
27+
name: string
28+
description: string
29+
subscribers_count: number
30+
stargazers_count: number
31+
forks_count: number
32+
}
33+
34+
@Component({
35+
changeDetection: ChangeDetectionStrategy.OnPush,
36+
selector: 'simple-example',
37+
standalone: true,
38+
template: `
39+
@if (query.isPending()) {
40+
Loading...
41+
}
42+
@if (query.error()) {
43+
An error has occurred: {{ query.error().message }}
44+
}
45+
@if (query.data(); as data) {
46+
<h1>{{ data.name }}</h1>
47+
<p>{{ data.description }}</p>
48+
<strong>👀 {{ data.subscribers_count }}</strong>
49+
<strong>✨ {{ data.stargazers_count }}</strong>
50+
<strong>🍴 {{ data.forks_count }}</strong>
51+
}
52+
53+
<angular-query-devtools initialIsOpen />
54+
`,
55+
imports: [AngularQueryDevtoolsComponent],
56+
})
57+
export class SimpleExampleComponent {
58+
http = inject(HttpClient)
59+
60+
query = injectQuery(() => ({
61+
queryKey: ['repoData'],
62+
queryFn: () =>
63+
lastValueFrom(
64+
this.http.get<Response>('https://api.github.com/repos/tannerlinsley/react-query')
65+
),
66+
}))
67+
}
68+
```

‎docs/angular/quick-start.md‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
id: quick-start
3+
title: Quick Start
4+
---
5+
6+
> VERY IMPORTANT: This library is currently in an experimental stage. This means that breaking changes will happen in minor AND patch releases. Use at your own risk. If you choose to rely on this in production in an experimental stage, please lock your version to a patch-level version to avoid unexpected breakages.
7+
8+
[//]: # 'Example'
9+
10+
If you're looking for a fully functioning example, please have a look at our [basic codesandbox example](../examples/angular/basic)
11+
12+
### Provide the client to your App
13+
14+
```typescript
15+
bootstrapApplication(AppComponent, {
16+
providers: [provideAngularQuery(new QueryClient())],
17+
})
18+
```
19+
20+
### Component with query and mutation
21+
22+
```typescript
23+
import {
24+
injectMutation,
25+
injectQuery,
26+
injectQueryClient
27+
} from '@tanstack/angular-query-experimental'
28+
import { getTodos, postTodo } from '../my-api'
29+
30+
@Component({
31+
standalone: true,
32+
template: `
33+
<div>
34+
<ul>
35+
@for (todo of query().data) {
36+
<li>{{ todo.title }}</li>
37+
}
38+
</ul>
39+
40+
<button (click)="onAddTodo()">Add Todo</button>
41+
</div>
42+
`,
43+
})
44+
export class TodosComponent {
45+
queryClient = injectQueryClient()
46+
47+
query = injectQuery(() => ({
48+
queryKey: ['todos'],
49+
queryFn: getTodos
50+
}))
51+
52+
mutation = injectMutation((client) => ({
53+
mutationFn: postTodo,
54+
onSuccess: () => {
55+
// Invalidate and refetch by using the client directly
56+
client.invalidateQueries({ queryKey: ['todos'] })
57+
58+
// OR use the queryClient that is injected into the component
59+
this.queryClient.invalidateQueries({ queryKey: ['todos'] })
60+
}
61+
}))
62+
63+
onAddTodo() {
64+
this.mutation().mutate({
65+
id: Date.now(),
66+
title: 'Do Laundry',
67+
})
68+
}
69+
}
70+
```
71+
72+
[//]: # 'Example'

‎docs/config.json‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,30 @@
816816
]
817817
}
818818
]
819+
},
820+
{"framework": "angular", "menuItems":[
821+
{
822+
"label": "Getting Started",
823+
"children": [
824+
{
825+
"label": "Overview",
826+
"to": "angular/overview"
827+
},
828+
{
829+
"label": "Installation",
830+
"to": "angular/installation"
831+
},
832+
{
833+
"label": "Quick Start",
834+
"to": "angular/quick-start"
835+
},
836+
{
837+
"label": "Devtools",
838+
"to": "angular/devtools"
839+
}
840+
]
841+
}
842+
]
819843
}
820844
],
821845
"users": [
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// @ts-check
2+
3+
/** @type {import('eslint').Linter.Config} */
4+
const config = {
5+
parserOptions: {
6+
tsconfigRootDir: __dirname,
7+
project: './tsconfig.json',
8+
},
9+
}
10+
11+
module.exports = config

‎examples/angular/basic/README.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Basic example
2+
3+
To run this example:
4+
5+
- `npm install` or `yarn` or `pnpm i`
6+
- `npm run dev` or `yarn dev` or `pnpm dev`

‎examples/angular/basic/index.html‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Angular Query basic example</title>
7+
</head>
8+
<body>
9+
<basic-example />
10+
<script type="module" src="src/index.ts"></script>
11+
</body>
12+
</html>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "@tanstack/query-example-angular-basic",
3+
"private": true,
4+
"type": "module",
5+
"version": "0.0.0",
6+
"description": "",
7+
"scripts": {
8+
"start": "vite",
9+
"dev": "vite",
10+
"build": "vite build",
11+
"serve": "vite preview"
12+
},
13+
"license": "MIT",
14+
"dependencies": {
15+
"@angular/common": "^17.0.2",
16+
"@angular/compiler": "^17.0.2",
17+
"@angular/core": "^17.0.2",
18+
"@angular/language-service": "^17.0.2",
19+
"@angular/platform-browser": "^17.0.2",
20+
"@tanstack/angular-query-experimental": "^5.0.0",
21+
"@tanstack/angular-query-devtools-experimental": "^5.0.0",
22+
"axios": "^1.5.1",
23+
"rxjs": "^7.8.1",
24+
"zone.js": "^0.14.2"
25+
},
26+
"devDependencies": {
27+
"typescript": "^5.2.2",
28+
"vite": "^4.5.0"
29+
}
30+
}

0 commit comments

Comments
 (0)