TanStack DB Angular 어댑터
설치
npm install @tanstack/angular-db
Angular inject 함수
Angular Adapter에서 사용할 수 있는 전체 함수 목록은 Angular Functions Reference를 참조할 수 있습니다.
쿼리 작성(필터링, 조인, 집계 등)에 관한 종합적인 문서는 Live Queries Guide를 참조할 수 있습니다.
기본 사용법
injectLiveQuery
injectLiveQuery 함수는 데이터가 변경될 때 컴포넌트를 자동으로 업데이트하는 라이브 쿼리를 생성합니다. 반응형 상태 관리를 위한 Angular 시그널이 포함된 객체를 반환합니다:
import { Component } from '@angular/core'
import { injectLiveQuery } from '@tanstack/angular-db'
import { eq } from '@tanstack/db'
@Component({
selector: 'app-todo-list',
standalone: true,
template: `
@if (query.isLoading()) {
<div>Loading...</div>
} @else {
<ul>
@for (todo of query.data(); track todo.id) {
<li>{{ todo.text }}</li>
}
</ul>
}
`
})
export class TodoListComponent {
query = injectLiveQuery((q) =>
q.from({ todos: todosCollection })
.where(({ todos }) => eq(todos.completed, false))
.select(({ todos }) => ({ id: todos.id, text: todos.text }))
)
}
참고: 모든 반환 값(data, isLoading, status 등)은 Angular 시그널이므로 템플릿에서 ()를 사용하여 호출해야 합니다: query.data(), query.isLoading().
템플릿 구문: 예제에서는 Angular 17 이상의 제어 흐름(
@if,@for)을 사용합니다. Angular 16에서는 대신*ngIf및*ngFor을 사용합니다.
반응형 매개변수
반응형 값에 의존하는 쿼리의 경우 params 옵션을 사용하여 해당 값이 변경될 때 쿼리를 다시 실행합니다:
import { Component, signal } from '@angular/core'
import { injectLiveQuery } from '@tanstack/angular-db'
import { gt } from '@tanstack/db'
@Component({
selector: 'app-filtered-todos',
standalone: true,
template: `
<div>{{ query.data().length }} high-priority todos</div>
`
})
export class FilteredTodosComponent {
minPriority = signal(5)
query = injectLiveQuery({
params: () => ({ minPriority: this.minPriority() }),
query: ({ params, q }) =>
q.from({ todos: todosCollection })
.where(({ todos }) => gt(todos.priority, params.minPriority))
})
}
반응형 매개변수를 사용하는 경우
쿼리가 다음 항목에 의존하는 경우 반응형 params 옵션을 사용합니다:
- 컴포넌트 시그널
- 입력 속성
- 계산된 값
- 기타 반응형 상태
params 함수에서 액세스하는 반응형 값이 변경되면 쿼리가 다시 생성되고 재실행됩니다.
매개변수가 변경되면 발생하는 동작
매개변수 값이 변경되면:
- 이전 라이브 쿼리 컬렉션이 폐기됩니다
- 업데이트된 매개변수 값으로 새 쿼리가 생성됩니다
status()/isLoading()이 새 쿼리의 수명 주기를 반영합니다- 새 결과가 도착하면
data()가 자동으로 업데이트됩니다
모범 사례
동적 쿼리에는 반응형 매개변수를 사용합니다:
import { Component, Input, signal } from '@angular/core'
import { injectLiveQuery } from '@tanstack/angular-db'
import { eq, and } from '@tanstack/db'
@Component({
selector: 'app-todo-list',
standalone: true,
template: `<div>{{ query.data().length }} todos</div>`
})
export class TodoListComponent {
// Angular 16+ compatible input
@Input({ required: true }) userId!: number
status = signal('active')
// Good - reactive params track all dependencies
query = injectLiveQuery({
params: () => ({
userId: this.userId,
status: this.status()
}),
query: ({ params, q }) =>
q.from({ todos: todosCollection })
.where(({ todos }) => and(
eq(todos.userId, params.userId),
eq(todos.status, params.status)
))
})
}
Angular 17+ 시그널 입력을 사용합니다:
import { Component, input, signal } from '@angular/core'
import { injectLiveQuery } from '@tanstack/angular-db'
import { eq, and } from '@tanstack/db'
@Component({
selector: 'app-todo-list',
standalone: true,
template: `<div>{{ query.data().length }} todos</div>`
})
export class TodoListComponent {
// Angular 17+ signal-based input
userId = input.required<number>()
status = signal('active')
query = injectLiveQuery({
params: () => ({
userId: this.userId(),
status: this.status()
}),
query: ({ params, q }) =>
q.from({ todos: todosCollection })
.where(({ todos }) => and(
eq(todos.userId, params.userId),
eq(todos.status, params.status)
))
})
}
정적 쿼리에는 매개변수가 필요하지 않습니다:
import { Component } from '@angular/core'
import { injectLiveQuery } from '@tanstack/angular-db'
@Component({
selector: 'app-all-todos',
standalone: true,
template: `<div>{{ query.data().length }} todos</div>`
})
export class AllTodosComponent {
// No reactive dependencies - query never changes
query = injectLiveQuery((q) =>
q.from({ todos: todosCollection })
)
}
템플릿에서 여러 시그널에 액세스합니다:
import { Component } from '@angular/core'
import { injectLiveQuery } from '@tanstack/angular-db'
import { eq } from '@tanstack/db'
@Component({
selector: 'app-todos',
standalone: true,
template: `
<div>Status: {{ query.status() }}</div>
<div>Loading: {{ query.isLoading() }}</div>
<div>Ready: {{ query.isReady() }}</div>
<div>Total: {{ query.data().length }}</div>
`
})
export class TodosComponent {
query = injectLiveQuery((q) =>
q.from({ todos: todosCollection })
.where(({ todos }) => eq(todos.completed, false))
)
}