Skip to content

Commit d1be49e

Browse files
committed
Merge remote-tracking branch 'upstream/main' into feature/angular-stable
2 parents 0fa7944 + 79608f3 commit d1be49e

File tree

27 files changed

+173
-163
lines changed

27 files changed

+173
-163
lines changed

Diff for: examples/angular/auto-refetching/src/app/components/auto-refetching.component.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,22 @@ import { TasksService } from '../services/tasks.service'
1111
@Component({
1212
changeDetection: ChangeDetectionStrategy.OnPush,
1313
selector: 'auto-refetching-example',
14-
standalone: true,
1514
templateUrl: './auto-refetching.component.html',
1615
imports: [NgStyle],
1716
})
1817
export class AutoRefetchingExampleComponent {
19-
#tasksService = inject(TasksService)
18+
readonly #tasksService = inject(TasksService)
2019

21-
intervalMs = signal(1000)
20+
readonly intervalMs = signal(1000)
2221

23-
tasks = injectQuery(() => this.#tasksService.allTasks(this.intervalMs()))
22+
readonly tasks = injectQuery(() =>
23+
this.#tasksService.allTasks(this.intervalMs()),
24+
)
2425

25-
addMutation = injectMutation(() => this.#tasksService.addTask())
26-
clearMutation = injectMutation(() => this.#tasksService.clearAllTasks())
26+
readonly addMutation = injectMutation(() => this.#tasksService.addTask())
27+
readonly clearMutation = injectMutation(() =>
28+
this.#tasksService.clearAllTasks(),
29+
)
2730

2831
clearTasks() {
2932
this.clearMutation.mutate()

Diff for: examples/angular/auto-refetching/src/app/services/tasks.service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import { lastValueFrom } from 'rxjs'
1212
providedIn: 'root',
1313
})
1414
export class TasksService {
15-
#queryClient = inject(QueryClient) // Manages query state and caching
16-
#http = inject(HttpClient) // Handles HTTP requests
15+
readonly #queryClient = inject(QueryClient) // Manages query state and caching
16+
readonly #http = inject(HttpClient) // Handles HTTP requests
1717

1818
/**
1919
* Fetches all tasks from the API.

Diff for: examples/angular/basic/src/app/app.component.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ import { PostsComponent } from './components/posts.component'
99
imports: [PostComponent, PostsComponent],
1010
})
1111
export class BasicExampleComponent {
12-
postId = signal(-1)
12+
readonly postId = signal(-1)
1313
}
+8-11
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,35 @@
11
import {
22
ChangeDetectionStrategy,
33
Component,
4-
EventEmitter,
5-
Output,
64
inject,
75
input,
6+
output,
87
} from '@angular/core'
9-
import { QueryClient, injectQuery } from '@tanstack/angular-query'
8+
import { injectQuery } from '@tanstack/angular-query'
109
import { fromEvent, lastValueFrom, takeUntil } from 'rxjs'
1110
import { PostsService } from '../services/posts-service'
1211

1312
@Component({
1413
changeDetection: ChangeDetectionStrategy.OnPush,
1514
selector: 'post',
15+
standalone: true,
1616
templateUrl: './post.component.html',
1717
})
1818
export class PostComponent {
19-
#postsService = inject(PostsService)
19+
readonly #postsService = inject(PostsService)
2020

21-
@Output() setPostId = new EventEmitter<number>()
21+
readonly setPostId = output<number>()
22+
readonly postId = input(0)
2223

23-
postId = input(0)
24-
25-
postQuery = injectQuery(() => ({
24+
readonly postQuery = injectQuery(() => ({
2625
enabled: this.postId() > 0,
2726
queryKey: ['post', this.postId()],
28-
queryFn: async (context) => {
27+
queryFn: (context) => {
2928
// Cancels the request when component is destroyed before the request finishes
3029
const abort$ = fromEvent(context.signal, 'abort')
3130
return lastValueFrom(
3231
this.#postsService.postById$(this.postId()).pipe(takeUntil(abort$)),
3332
)
3433
},
3534
}))
36-
37-
queryClient = inject(QueryClient)
3835
}

Diff for: examples/angular/basic/src/app/components/posts.component.html

+26-30
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,31 @@
11
<div>
22
<h1>Posts</h1>
3-
@switch (postsQuery.status()) {
4-
@case ('pending') {
5-
Loading...
6-
}
7-
@case ('error') {
8-
Error: {{ postsQuery.error()?.message }}
9-
}
10-
@default {
11-
<div class="todo-container">
12-
@for (post of postsQuery.data(); track post.id) {
13-
<p>
14-
<!-- We can access the query data here to show bold links for-->
15-
<!-- ones that are cached-->
16-
<a
17-
href="#"
18-
(click)="setPostId.emit(post.id)"
19-
[style]="
20-
queryClient.getQueryData(['post', post.id])
21-
? {
22-
fontWeight: 'bold',
23-
color: 'green',
24-
}
25-
: {}
26-
"
27-
>{{ post.title }}</a
28-
>
29-
</p>
30-
}
31-
</div>
32-
}
3+
@if (postsQuery.isPending()) {
4+
Loading...
5+
} @else if (postsQuery.isError()) {
6+
Error: {{ postsQuery.error().message }}
7+
} @else if (postsQuery.isSuccess()) {
8+
<div class="todo-container">
9+
@for (post of postsQuery.data(); track post.id) {
10+
<p>
11+
<!-- We can access the query data here to show bold links for-->
12+
<!-- ones that are cached-->
13+
<a
14+
href="#"
15+
(click)="setPostId.emit(post.id)"
16+
[style]="
17+
queryClient.getQueryData(['post', post.id])
18+
? {
19+
fontWeight: 'bold',
20+
color: 'green',
21+
}
22+
: {}
23+
"
24+
>{{ post.title }}</a
25+
>
26+
</p>
27+
}
28+
</div>
3329
}
3430
<div>
3531
@if (postsQuery.isFetching()) {

Diff for: examples/angular/basic/src/app/components/posts.component.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import {
22
ChangeDetectionStrategy,
33
Component,
4-
EventEmitter,
5-
Output,
64
inject,
5+
output,
76
} from '@angular/core'
87
import { QueryClient, injectQuery } from '@tanstack/angular-query'
98
import { lastValueFrom } from 'rxjs'
@@ -15,12 +14,11 @@ import { PostsService } from '../services/posts-service'
1514
templateUrl: './posts.component.html',
1615
})
1716
export class PostsComponent {
18-
queryClient = inject(QueryClient)
19-
#postsService = inject(PostsService)
17+
readonly queryClient = inject(QueryClient)
18+
readonly #postsService = inject(PostsService)
19+
readonly setPostId = output<number>()
2020

21-
@Output() setPostId = new EventEmitter<number>()
22-
23-
postsQuery = injectQuery(() => ({
21+
readonly postsQuery = injectQuery(() => ({
2422
queryKey: ['posts'],
2523
queryFn: () => lastValueFrom(this.#postsService.allPosts$()),
2624
}))

Diff for: examples/angular/basic/src/app/services/posts-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Injectable, inject } from '@angular/core'
55
providedIn: 'root',
66
})
77
export class PostsService {
8-
#http = inject(HttpClient)
8+
readonly #http = inject(HttpClient)
99

1010
postById$ = (postId: number) =>
1111
this.#http.get<Post>(`https://jsonplaceholder.typicode.com/posts/${postId}`)

Diff for: examples/angular/devtools-panel/src/app/app.config.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { provideRouter } from '@angular/router'
44
import {
55
QueryClient,
66
provideTanStackQuery,
7-
withDevtools,
87
} from '@tanstack/angular-query'
98
import { routes } from './app.routes'
109
import type { ApplicationConfig } from '@angular/core'
@@ -13,6 +12,6 @@ export const appConfig: ApplicationConfig = {
1312
providers: [
1413
provideHttpClient(withFetch()),
1514
provideRouter(routes),
16-
provideTanStackQuery(new QueryClient(), withDevtools()),
15+
provideTanStackQuery(new QueryClient()),
1716
],
1817
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { ChangeDetectionStrategy, Component, viewChild } from '@angular/core'
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
signal,
5+
viewChild,
6+
} from '@angular/core'
27
import { injectDevtoolsPanel } from '@tanstack/angular-query-devtools-experimental'
38
import { ExampleQueryComponent } from './example-query.component'
49
import type { ElementRef } from '@angular/core'
@@ -13,20 +18,24 @@ import type { ElementRef } from '@angular/core'
1318
In this example, the devtools panel is loaded programmatically when the
1419
button is clicked
1520
</p>
16-
<button type="button" (click)="isOpen = !isOpen">
17-
{{ isOpen ? 'Close' : 'Open' }} the devtools panel
21+
<button type="button" (click)="toggleIsOpen()">
22+
{{ isOpen() ? 'Close' : 'Open' }} the devtools panel
1823
</button>
19-
@if (isOpen) {
24+
@if (isOpen()) {
2025
<div #div style="height: 500px"></div>
2126
}
2227
`,
2328
imports: [ExampleQueryComponent],
2429
})
2530
export default class BasicDevtoolsPanelExampleComponent {
26-
isOpen = false
27-
divEl = viewChild<ElementRef>('div')
31+
readonly isOpen = signal(false)
32+
readonly divEl = viewChild<ElementRef>('div')
2833

29-
devtools = injectDevtoolsPanel(() => ({
34+
toggleIsOpen() {
35+
this.isOpen.update((prev) => !prev)
36+
}
37+
38+
readonly devtools = injectDevtoolsPanel(() => ({
3039
hostElement: this.divEl(),
3140
}))
3241
}

Diff for: examples/angular/devtools-panel/src/app/components/example-query.component.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ interface Response {
3333
`,
3434
})
3535
export class ExampleQueryComponent {
36-
#http = inject(HttpClient)
36+
readonly #http = inject(HttpClient)
3737

38-
query = injectQuery(() => ({
38+
readonly query = injectQuery(() => ({
3939
queryKey: ['repoData'],
4040
queryFn: () =>
4141
lastValueFrom(

Diff for: examples/angular/devtools-panel/src/app/components/lazy-load-devtools-panel-example.component.ts

+23-16
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import {
33
Component,
44
Injector,
55
computed,
6+
effect,
67
inject,
8+
signal,
79
viewChild,
810
} from '@angular/core'
911
import { ExampleQueryComponent } from './example-query.component'
@@ -20,33 +22,38 @@ import type { DevtoolsPanelRef } from '@tanstack/angular-query-devtools-experime
2022
In this example, the devtools panel is loaded programmatically when the
2123
button is clicked. In addition, the code is lazy loaded.
2224
</p>
23-
<button type="button" (click)="toggleDevtools()">
24-
{{ isOpen ? 'Close' : 'Open' }} the devtools panel
25+
<button type="button" (click)="toggleIsOpen()">
26+
{{ isOpen() ? 'Close' : 'Open' }} the devtools panel
2527
</button>
26-
@if (isOpen) {
28+
@if (isOpen()) {
2729
<div #div style="height: 500px"></div>
2830
}
2931
`,
3032
imports: [ExampleQueryComponent],
3133
})
3234
export default class LazyLoadDevtoolsPanelExampleComponent {
33-
isOpen = false
34-
devtools?: Promise<DevtoolsPanelRef>
35-
injector = inject(Injector)
35+
readonly isOpen = signal(false)
36+
readonly devtools = signal<Promise<DevtoolsPanelRef> | undefined>(undefined)
37+
readonly injector = inject(Injector)
3638

37-
divEl = viewChild<ElementRef>('div')
38-
devToolsOptions = computed(() => ({
39+
readonly divEl = viewChild<ElementRef>('div')
40+
readonly devToolsOptions = computed(() => ({
3941
hostElement: this.divEl(),
4042
}))
4143

42-
toggleDevtools() {
43-
this.isOpen = !this.isOpen
44-
if (!this.devtools) {
45-
this.devtools = import(
46-
'@tanstack/angular-query-devtools-experimental'
47-
).then(({ injectDevtoolsPanel }) =>
48-
injectDevtoolsPanel(this.devToolsOptions, this.injector),
44+
toggleIsOpen() {
45+
this.isOpen.update((prev) => !prev)
46+
}
47+
48+
readonly loadDevtoolsEffect = effect(() => {
49+
if (this.devtools()) return
50+
if (this.isOpen()) {
51+
this.devtools.set(
52+
import('@tanstack/angular-query-devtools-experimental').then(
53+
({ injectDevtoolsPanel }) =>
54+
injectDevtoolsPanel(this.devToolsOptions, this.injector),
55+
),
4956
)
5057
}
51-
}
58+
})
5259
}

Diff for: examples/angular/infinite-query-with-max-pages/src/app/components/example.component.ts

+12-10
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import { ProjectsService } from '../services/projects.service'
1616
imports: [ProjectStyleDirective],
1717
})
1818
export class ExampleComponent {
19-
projectsService = inject(ProjectsService)
19+
readonly projectsService = inject(ProjectsService)
2020

21-
query = injectInfiniteQuery(() => ({
21+
readonly query = injectInfiniteQuery(() => ({
2222
queryKey: ['projects'],
2323
queryFn: ({ pageParam }) => {
2424
return lastValueFrom(this.projectsService.getProjects(pageParam))
@@ -29,29 +29,31 @@ export class ExampleComponent {
2929
maxPages: 3,
3030
}))
3131

32-
nextButtonDisabled = computed(
32+
readonly nextButtonDisabled = computed(
3333
() => !this.#hasNextPage() || this.#isFetchingNextPage(),
3434
)
35-
nextButtonText = computed(() =>
35+
36+
readonly nextButtonText = computed(() =>
3637
this.#isFetchingNextPage()
3738
? 'Loading more...'
3839
: this.#hasNextPage()
3940
? 'Load newer'
4041
: 'Nothing more to load',
4142
)
42-
previousButtonDisabled = computed(
43+
44+
readonly previousButtonDisabled = computed(
4345
() => !this.#hasPreviousPage() || this.#isFetchingNextPage(),
4446
)
45-
previousButtonText = computed(() =>
47+
readonly previousButtonText = computed(() =>
4648
this.#isFetchingPreviousPage()
4749
? 'Loading more...'
4850
: this.#hasPreviousPage()
4951
? 'Load Older'
5052
: 'Nothing more to load',
5153
)
5254

53-
#hasPreviousPage = this.query.hasPreviousPage
54-
#hasNextPage = this.query.hasNextPage
55-
#isFetchingPreviousPage = this.query.isFetchingPreviousPage
56-
#isFetchingNextPage = this.query.isFetchingNextPage
55+
readonly #hasPreviousPage = this.query.hasPreviousPage
56+
readonly #hasNextPage = this.query.hasNextPage
57+
readonly #isFetchingPreviousPage = this.query.isFetchingPreviousPage
58+
readonly #isFetchingNextPage = this.query.isFetchingNextPage
5759
}

0 commit comments

Comments
 (0)