Skip to main content Inicio Creadores tanstack db angular-db
angular-db Angular bindings for TanStack DB. injectLiveQuery inject function with Angular signals (Signal<T>) for all return values. Reactive params pattern ({ params: () => T, query: ({ params, q }) => QueryBuilder }) for dynamic queries. Must be called in injection context. Angular 17+ control flow (@if, @for) and signal inputs supported. Import from @tanstack/angular-db (re-exports all of @tanstack/db).
Ir a la instalación Skills Marketplace Descubre y explora habilidades de IA creadas por la comunidad.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Copiar promptMostrar detalles del prompt Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/TanStack/db --skill angular-dbEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Descargar Zip Descargando... Más de este repositorio Creating typed collections with createCollection. Adapter selection: queryCollectionOptions (REST/TanStack Query), electricCollectionOptions (ElectricSQL real-time sync), powerSyncCollectionOptions (PowerSync SQLite), rxdbCollectionOptions (RxDB), trailBaseCollectionOptions (TrailBase), localOnlyCollectionOptions, localStorageCollectionOptions. CollectionConfig options: getKey, schema, sync, gcTime, autoIndex (default off), defaultIndexType, syncMode (eager/on-demand, plus progressive for Electric). StandardSchema validation with Zod/Valibot/ArkType. Collection lifecycle (idle/loading/ready/error). Adapter-specific sync patterns including Electric txid tracking, Query direct writes, Query initial data and scoped factories, and PowerSync query-driven sync with onLoad/onLoadSubset hooks.
Building custom collection adapters for new backends. SyncConfig interface: sync function receiving begin, write, commit, markReady, truncate, metadata primitives and returning cleanup, loadSubset, and optional unloadSubset handlers. ChangeMessage format (insert, update, delete). On-demand LoadSubsetOptions (where, orderBy, limit, offset, cursor). Expression parsing: parseWhereExpression, parseOrderByExpression, extractSimpleComparisons, parseLoadSubsetOptions. Collection options creator pattern. rowUpdateMode (partial vs full). Subscription lifecycle and cleanup functions. Persisted sync metadata API (metadata.row and metadata.collection) for storing per-row and per-collection adapter state.
Query builder fluent API: from, where, join, leftJoin, rightJoin, innerJoin, fullJoin, select, fn.select, groupBy, having, orderBy, limit, offset, distinct, findOne. Operators: eq, gt, gte, lt, lte, like, ilike, inArray, isNull, isUndefined, and, or, not. Aggregates: count, sum, avg, min, max. String functions: upper, lower, length, concat. Utility: coalesce, caseWhen. Math: add, subtract, multiply, divide. $selected namespace. createLiveQueryCollection. Derived collections. Predicate push-down. Incremental view maintenance via differential dataflow (d2ts). Virtual properties ($synced, $origin, $key, $collectionId). Includes subqueries for hierarchical data. Collection, toArray, materialize, and concat(toArray(...)) include modes. queryOnce for one-shot queries. createEffect for reactive side effects (onEnter, onUpdate, onExit, onBatch).
name angular-db description Angular bindings for TanStack DB. injectLiveQuery inject function with Angular signals (Signal<T>) for all return values. Reactive params pattern ({ params: () => T, query: ({ params, q }) => QueryBuilder }) for dynamic queries. Must be called in injection context. Angular 17+ control flow (@if, @for) and signal inputs supported. Import from @tanstack/angular-db (re-exports all of @tanstack/db).
type framework library db framework angular library_version 0.6.17 requires ["db-core"] sources ["TanStack/db:docs/framework/angular/overview.md","TanStack/db:packages/angular-db/src/index.ts"]
This skill builds on db-core. Read it first for collection setup, query builder, and mutation patterns.
TanStack DB — Angular
Setup
import { Component } from '@angular/core'
import { injectLiveQuery, eq, not } from '@tanstack/angular-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 } ) => not (todos.completed ))
.orderBy (({ todos } ) => todos.created_at , 'asc' ),
)
}
@tanstack/angular-db re-exports everything from @tanstack/db.
Inject Function
injectLiveQuery
Returns an object with Angular Signal<T> properties — call with () in templates:
const query = injectLiveQuery ((q ) => q. ({ : todoCollection }))
query = ({
: ({ : . () }),
:
q
. ({ : todoCollection })
. ( (todo. , params. )),
})
query = ({
: q. ({ : todoCollection }),
: ,
})
query = (preloadedCollection)
query = ({
: ({ : . () }),
: {
(!params. )
q
. ({ : todoCollection })
. ( (todo. , params. ))
},
})
from
todo
const
injectLiveQuery
params
() =>
minPriority
this
minPriority
query
({ params, q } ) =>
from
todo
where
({ todo } ) =>
gt
priority
minPriority
const
injectLiveQuery
query
(q ) =>
from
todo
gcTime
60000
const
injectLiveQuery
const
injectLiveQuery
params
() =>
userId
this
userId
query
({ params, q } ) =>
if
userId
return
undefined
return
from
todo
where
({ todo } ) =>
eq
userId
userId
A bare { query } config defaults to startSync: true and gcTime: 0, like
the query-function overload. Explicit values in the config override those
defaults.
Angular-Specific Patterns
Reactive params with signals @Component ({
selector : 'app-filtered-todos' ,
standalone : true ,
template : `<div>{{ query.data().length }} 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 )),
})
}
When params() return value changes, the previous collection is disposed and a new query is created.
Signal inputs (Angular 17+) @Component ({
selector : 'app-user-todos' ,
standalone : true ,
template : `<div>{{ query.data().length }} todos</div>` ,
})
export class UserTodosComponent {
userId = input.required <number >()
query = injectLiveQuery ({
params : () => ({ userId : this .userId () }),
query : ({ params, q } ) =>
q
.from ({ todo : todoCollection })
.where (({ todo } ) => eq (todo.userId , params.userId )),
})
}
Legacy @Input (Angular 16) export class UserTodosComponent {
@Input ({ required : true }) userId!: number
query = injectLiveQuery ({
params : () => ({ userId : this .userId }),
query : ({ params, q } ) =>
q
.from ({ todo : todoCollection })
.where (({ todo } ) => eq (todo.userId , params.userId )),
})
}
Template syntax Angular 17+ control flow:
@if (query.isLoading()) {
<div > Loading...</div >
} @else { @for (todo of query.data(); track todo.id) {
<li > {{ todo.text }}</li >
} }
Angular 16 structural directives:
<div *ngIf ="query.isLoading()" > Loading...</div >
<li *ngFor ="let todo of query.data(); trackBy: trackById" > {{ todo.text }}</li >
Includes (Hierarchical Data) When a query uses includes (subqueries in select), each child field is a live Collection by default. Subscribe to it with injectLiveQuery in a child component:
@Component ({
selector : 'app-project-list' ,
standalone : true ,
imports : [IssueListComponent ],
template : `
@for (project of query.data(); track project.id) {
<div>
{{ project.name }}
<app-issue-list [issuesCollection]="project.issues" />
</div>
}
` ,
})
export class ProjectListComponent {
query = injectLiveQuery ((q ) =>
q.from ({ p : projectsCollection }).select (({ p } ) => ({
id : p.id ,
name : p.name ,
issues : q
.from ({ i : issuesCollection })
.where (({ i } ) => eq (i.projectId , p.id ))
.select (({ i } ) => ({ id : i.id , title : i.title })),
})),
)
}
@Component ({
selector : 'app-issue-list' ,
standalone : true ,
template : `
@for (issue of query.data(); track issue.id) {
<li>{{ issue.title }}</li>
}
` ,
})
export class IssueListComponent {
issuesCollection = input.required <Collection >()
query = injectLiveQuery (this .issuesCollection ())
}
With toArray(), child results are plain arrays and the parent re-emits on child changes:
import { toArray, eq } from '@tanstack/angular-db'
query = injectLiveQuery ((q ) =>
q.from ({ p : projectsCollection }).select (({ p } ) => ({
id : p.id ,
name : p.name ,
issues : toArray (
q
.from ({ i : issuesCollection })
.where (({ i } ) => eq (i.projectId , p.id ))
.select (({ i } ) => ({ id : i.id , title : i.title })),
),
})),
)
See db-core/live-queries/SKILL.md for full includes rules (correlation conditions, nested includes, aggregates).
Common Mistakes
CRITICAL Using injectLiveQuery outside injection context export class TodoComponent {
ngOnInit ( ) {
this .query = injectLiveQuery ((q ) => q.from ({ todo : todoCollection }))
}
}
export class TodoComponent {
query = injectLiveQuery ((q ) => q.from ({ todo : todoCollection }))
}
injectLiveQuery calls assertInInjectionContext internally — it must be called during construction (field initializer or constructor), not in lifecycle hooks.
Source: packages/angular-db/src/index.ts
HIGH Using query function for reactive values instead of params export class FilteredComponent {
status = signal ('active' )
query = injectLiveQuery ((q ) =>
q
.from ({ todo : todoCollection })
.where (({ todo } ) => eq (todo.status , this .status ())),
)
}
export class FilteredComponent {
status = signal ('active' )
query = injectLiveQuery ({
params : () => ({ status : this .status () }),
query : ({ params, q } ) =>
q
.from ({ todo : todoCollection })
.where (({ todo } ) => eq (todo.status , params.status )),
})
}
The plain query function overload does not track Angular signal reads. Use the params pattern to make reactive values trigger query re-creation.
Source: packages/angular-db/src/index.ts
MEDIUM Forgetting to call signals in templates <div > {{ query.data.length }}</div >
<div > {{ query.data().length }}</div >
All return values are Angular signals. Without (), you get the signal object, not the value.
See also: db-core/live-queries/SKILL.md — for query builder API.
See also: db-core/mutations-optimistic/SKILL.md — for mutation patterns.