From 0a4adf413de2fe3f8520fef8f2f531f201ef0ae9 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Nov 2025 21:39:12 +0000 Subject: [PATCH 1/4] docs: add framework overview pages for Vue, Solid, Svelte, and Angular Replace placeholder content with complete framework-specific documentation for all non-React adapters. Each overview includes: - Installation instructions - Basic usage with useLiveQuery (or injectLiveQuery for Angular) - Dependency arrays/reactive parameters documentation - Framework-specific code examples and best practices These pages follow the same structure as the React overview but are tailored to each framework's conventions and only document the useLiveQuery hook (the only hook currently available for these frameworks). --- docs/framework/angular/overview.md | 159 +++++++++++++++++++++++++++++ docs/framework/solid/overview.md | 143 +++++++++++++++++++++++++- docs/framework/svelte/overview.md | 143 +++++++++++++++++++++++++- docs/framework/vue/overview.md | 137 ++++++++++++++++++++++++- 4 files changed, 576 insertions(+), 6 deletions(-) diff --git a/docs/framework/angular/overview.md b/docs/framework/angular/overview.md index d4b911614..d3539f7e8 100644 --- a/docs/framework/angular/overview.md +++ b/docs/framework/angular/overview.md @@ -13,4 +13,163 @@ npm install @tanstack/angular-db See the [Angular Functions Reference](../reference/index.md) to see the full list of functions available in the Angular Adapter. +For comprehensive documentation on writing queries (filtering, joins, aggregations, etc.), see the [Live Queries Guide](../../guides/live-queries). + ## Basic Usage + +### injectLiveQuery + +The `injectLiveQuery` function creates a live query that automatically updates your component when data changes. It returns Angular signals for reactive state management: + +```typescript +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 (isLoading()) { +
Loading...
+ } @else { + + } + ` +}) +export class TodoListComponent { + { data, isLoading } = injectLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => eq(todos.completed, false)) + .select(({ todos }) => ({ id: todos.id, text: todos.text })) + ) +} +``` + +### Reactive Parameters + +For queries that depend on reactive values, use the `params` option to re-run the query when those values change: + +```typescript +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: ` +
{{ data().length }} high-priority todos
+ ` +}) +export class FilteredTodosComponent { + minPriority = signal(5) + + { data } = injectLiveQuery({ + params: () => ({ minPriority: this.minPriority() }), + query: ({ params, q }) => + q.from({ todos: todosCollection }) + .where(({ todos }) => gt(todos.priority, params.minPriority)) + }) +} +``` + +#### When to Use Reactive Parameters + +Use the reactive `params` option when your query depends on: +- Component signals +- Input properties +- Computed values +- Other reactive state + +When any reactive value accessed in the `params` function changes, the query is recreated and re-executed. + +#### What Happens When Parameters Change + +When a parameter value changes: +1. The previous live query collection is cleaned up +2. A new query is created with the updated parameter values +3. The component updates automatically through Angular's signals +4. The `isLoading` signal becomes `true` until the new data is ready + +#### Best Practices + +**Use reactive params for dynamic queries:** + +```typescript +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: `
{{ data().length }} todos
` +}) +export class TodoListComponent { + userId = input.required() + status = signal('active') + + // Good - reactive params track all dependencies + { data } = 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) + )) + }) +} +``` + +**Static queries don't need params:** + +```typescript +import { Component } from '@angular/core' +import { injectLiveQuery } from '@tanstack/angular-db' + +@Component({ + selector: 'app-all-todos', + standalone: true, + template: `
{{ data().length }} todos
` +}) +export class AllTodosComponent { + // No reactive dependencies - query never changes + { data } = injectLiveQuery((q) => + q.from({ todos: todosCollection }) + ) +} +``` + +**Access signals directly in template:** + +```typescript +import { Component } from '@angular/core' +import { injectLiveQuery } from '@tanstack/angular-db' +import { eq } from '@tanstack/db' + +@Component({ + selector: 'app-todos', + standalone: true, + template: ` +
Status: {{ status() }}
+
Loading: {{ isLoading() }}
+
Ready: {{ isReady() }}
+
Total: {{ data().length }}
+ ` +}) +export class TodosComponent { + { data, status, isLoading, isReady } = injectLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => eq(todos.completed, false)) + ) +} +``` diff --git a/docs/framework/solid/overview.md b/docs/framework/solid/overview.md index c5cde978a..7d5fe3d7e 100644 --- a/docs/framework/solid/overview.md +++ b/docs/framework/solid/overview.md @@ -1,5 +1,144 @@ --- title: TanStack DB Solid Adapter -ref: docs/framework/react/adapter.md -replace: { "React": "Solid", "react": "solid" } +id: adapter --- + +## Installation + +```sh +npm install @tanstack/solid-db +``` + +## Solid Primitives + +See the [Solid Functions Reference](../reference/index.md) to see the full list of primitives available in the Solid Adapter. + +For comprehensive documentation on writing queries (filtering, joins, aggregations, etc.), see the [Live Queries Guide](../../guides/live-queries). + +## Basic Usage + +### useLiveQuery + +The `useLiveQuery` primitive creates a live query that automatically updates your component when data changes: + +```tsx +import { useLiveQuery } from '@tanstack/solid-db' +import { eq } from '@tanstack/db' +import { Show, For } from 'solid-js' + +function TodoList() { + const { data, isLoading } = useLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => eq(todos.completed, false)) + .select(({ todos }) => ({ id: todos.id, text: todos.text })) + ) + + return ( + Loading...}> +
    + + {(todo) =>
  • {todo.text}
  • } +
    +
+
+ ) +} +``` + +### Dependency Arrays + +The `useLiveQuery` primitive accepts an optional dependency array as its last parameter. This array works similarly to Solid's `createEffect` dependencies - when any value in the array changes, the query is recreated and re-executed. + +#### When to Use Dependency Arrays + +Use dependency arrays when your query depends on external reactive values (props or signals): + +```tsx +import { useLiveQuery } from '@tanstack/solid-db' +import { gt } from '@tanstack/db' + +function FilteredTodos(props: { minPriority: number }) { + const { data } = useLiveQuery( + (q) => q.from({ todos: todosCollection }) + .where(({ todos }) => gt(todos.priority, props.minPriority)), + [() => props.minPriority] // Re-run when minPriority changes + ) + + return
{data().length} high-priority todos
+} +``` + +**Note:** When using props or signals in the query, wrap them in a function for the dependency array. + +#### What Happens When Dependencies Change + +When a dependency value changes: +1. The previous live query collection is cleaned up +2. A new query is created with the updated values +3. The component re-renders with the new data +4. The primitive shows loading state again + +#### Best Practices + +**Include all external values used in the query:** + +```tsx +import { createSignal } from 'solid-js' +import { useLiveQuery } from '@tanstack/solid-db' +import { eq, and } from '@tanstack/db' + +function TodoList() { + const [userId, setUserId] = createSignal(1) + const [status, setStatus] = createSignal('active') + + // Good - all external values in deps + const { data } = useLiveQuery( + (q) => q.from({ todos: todosCollection }) + .where(({ todos }) => and( + eq(todos.userId, userId()), + eq(todos.status, status()) + )), + [userId, status] + ) + + // Bad - missing dependencies + const { data: badData } = useLiveQuery( + (q) => q.from({ todos: todosCollection }) + .where(({ todos }) => eq(todos.userId, userId())), + [] // Missing userId! + ) + + return
{data().length} todos
+} +``` + +**Empty array for static queries:** + +```tsx +import { useLiveQuery } from '@tanstack/solid-db' + +function AllTodos() { + // No external dependencies - query never changes + const { data } = useLiveQuery( + (q) => q.from({ todos: todosCollection }), + [] + ) + + return
{data().length} todos
+} +``` + +**Omit the array for queries with no external dependencies:** + +```tsx +import { useLiveQuery } from '@tanstack/solid-db' + +function AllTodos() { + // Same as above - no deps needed + const { data } = useLiveQuery( + (q) => q.from({ todos: todosCollection }) + ) + + return
{data().length} todos
+} +``` diff --git a/docs/framework/svelte/overview.md b/docs/framework/svelte/overview.md index 079ec6d9b..0adaed472 100644 --- a/docs/framework/svelte/overview.md +++ b/docs/framework/svelte/overview.md @@ -1,5 +1,144 @@ --- title: TanStack DB Svelte Adapter -ref: docs/framework/react/adapter.md -replace: { "React": "Svelte", "react": "svelte" } +id: adapter --- + +## Installation + +```sh +npm install @tanstack/svelte-db +``` + +## Svelte Utilities + +See the [Svelte Functions Reference](../reference/index.md) to see the full list of utilities available in the Svelte Adapter. + +For comprehensive documentation on writing queries (filtering, joins, aggregations, etc.), see the [Live Queries Guide](../../guides/live-queries). + +## Basic Usage + +### useLiveQuery + +The `useLiveQuery` utility creates a live query that automatically updates your component when data changes: + +```svelte + + +{#if $isLoading} +
Loading...
+{:else} + +{/if} +``` + +### Dependency Arrays + +The `useLiveQuery` utility accepts an optional dependency array as its last parameter. When any value in the array changes, the query is recreated and re-executed. + +#### When to Use Dependency Arrays + +Use dependency arrays when your query depends on external reactive values (props or state): + +```svelte + + +
{$data.length} high-priority todos
+``` + +**Note:** When using props or reactive state in the query, wrap them in a function for the dependency array. + +#### What Happens When Dependencies Change + +When a dependency value changes: +1. The previous live query collection is cleaned up +2. A new query is created with the updated values +3. The component re-renders with the new data +4. The utility shows loading state again + +#### Best Practices + +**Include all external values used in the query:** + +```svelte + + +
{$data.length} todos
+``` + +**Empty array for static queries:** + +```svelte + + +
{$data.length} todos
+``` + +**Omit the array for queries with no external dependencies:** + +```svelte + + +
{$data.length} todos
+``` diff --git a/docs/framework/vue/overview.md b/docs/framework/vue/overview.md index 533fc7a2e..9cb45017a 100644 --- a/docs/framework/vue/overview.md +++ b/docs/framework/vue/overview.md @@ -1,5 +1,138 @@ --- title: TanStack DB Vue Adapter -ref: docs/framework/react/adapter.md -replace: { "React": "Vue", "react": "vue" } +id: adapter --- + +## Installation + +```sh +npm install @tanstack/vue-db +``` + +## Vue Composables + +See the [Vue Functions Reference](../reference/index.md) to see the full list of composables available in the Vue Adapter. + +For comprehensive documentation on writing queries (filtering, joins, aggregations, etc.), see the [Live Queries Guide](../../guides/live-queries). + +## Basic Usage + +### useLiveQuery + +The `useLiveQuery` composable creates a live query that automatically updates your component when data changes: + +```vue + + + +``` + +### Dependency Arrays + +The `useLiveQuery` composable accepts an optional dependency array as its last parameter. This array works similarly to Vue's `watchEffect` dependencies - when any value in the array changes, the query is recreated and re-executed. + +#### When to Use Dependency Arrays + +Use dependency arrays when your query depends on external reactive values (props, refs, or other composables): + +```vue + + + +``` + +**Note:** When using props or refs in the query, wrap them in a function for the dependency array. + +#### What Happens When Dependencies Change + +When a dependency value changes: +1. The previous live query collection is cleaned up +2. A new query is created with the updated values +3. The component re-renders with the new data +4. The composable shows loading state again + +#### Best Practices + +**Include all external values used in the query:** + +```vue + +``` + +**Empty array for static queries:** + +```vue + +``` + +**Omit the array for queries with no external dependencies:** + +```vue + +``` From e3acb098328f72c3ea32182da3c8526f209b1df6 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Nov 2025 21:50:23 +0000 Subject: [PATCH 2/4] docs: fix reactivity patterns in Solid and Vue framework overviews Correct the documentation based on actual source code and test verification: **Solid changes:** - Remove incorrect dependency array pattern - Document automatic fine-grained reactivity tracking - Show correct signal usage inside query functions - Add examples of good vs bad patterns - Explain that Solid tracks signals automatically without deps **Vue changes:** - Fix dependency array to pass refs directly, not wrapped in functions - Show correct pattern: [minAge] instead of [() => minAge] - Add toRef pattern for props - Clarify getter functions are only needed for non-ref values - Add example of using pre-created collections with reactive refs Both frameworks now match their actual implementations as verified against packages/*-db/src/*.ts source files and test files. --- docs/framework/solid/overview.md | 149 ++++++++++++++++++++----------- docs/framework/vue/overview.md | 97 +++++++++++++++++--- 2 files changed, 184 insertions(+), 62 deletions(-) diff --git a/docs/framework/solid/overview.md b/docs/framework/solid/overview.md index 7d5fe3d7e..d9a90854b 100644 --- a/docs/framework/solid/overview.md +++ b/docs/framework/solid/overview.md @@ -19,7 +19,7 @@ For comprehensive documentation on writing queries (filtering, joins, aggregatio ### useLiveQuery -The `useLiveQuery` primitive creates a live query that automatically updates your component when data changes: +The `useLiveQuery` primitive creates a live query that automatically updates your component when data changes. All return values are reactive and should be called as functions: ```tsx import { useLiveQuery } from '@tanstack/solid-db' @@ -27,16 +27,16 @@ import { eq } from '@tanstack/db' import { Show, For } from 'solid-js' function TodoList() { - const { data, isLoading } = useLiveQuery((q) => + const query = useLiveQuery((q) => q.from({ todos: todosCollection }) .where(({ todos }) => eq(todos.completed, false)) .select(({ todos }) => ({ id: todos.id, text: todos.text })) ) return ( - Loading...}> + Loading...}>
    - + {(todo) =>
  • {todo.text}
  • }
@@ -45,42 +45,34 @@ function TodoList() { } ``` -### Dependency Arrays +**Note:** `query.data` returns an array directly (not a function), but status fields like `isLoading()`, `status()`, etc. are accessor functions. -The `useLiveQuery` primitive accepts an optional dependency array as its last parameter. This array works similarly to Solid's `createEffect` dependencies - when any value in the array changes, the query is recreated and re-executed. +### Reactive Queries with Signals -#### When to Use Dependency Arrays - -Use dependency arrays when your query depends on external reactive values (props or signals): +Solid uses fine-grained reactivity, which means queries automatically track and respond to signal changes. Simply call signals inside your query function, and Solid will automatically recompute when they change: ```tsx +import { createSignal } from 'solid-js' import { useLiveQuery } from '@tanstack/solid-db' import { gt } from '@tanstack/db' function FilteredTodos(props: { minPriority: number }) { - const { data } = useLiveQuery( - (q) => q.from({ todos: todosCollection }) - .where(({ todos }) => gt(todos.priority, props.minPriority)), - [() => props.minPriority] // Re-run when minPriority changes + const query = useLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => gt(todos.priority, props.minPriority)) ) - return
{data().length} high-priority todos
+ return
{query.data.length} high-priority todos
} ``` -**Note:** When using props or signals in the query, wrap them in a function for the dependency array. +When `props.minPriority` changes, Solid's reactivity system automatically: +1. Detects the prop access inside the query function +2. Cleans up the previous live query collection +3. Creates a new query with the updated value +4. Updates the component with the new data -#### What Happens When Dependencies Change - -When a dependency value changes: -1. The previous live query collection is cleaned up -2. A new query is created with the updated values -3. The component re-renders with the new data -4. The primitive shows loading state again - -#### Best Practices - -**Include all external values used in the query:** +#### Using Signals from Component State ```tsx import { createSignal } from 'solid-js' @@ -91,54 +83,107 @@ function TodoList() { const [userId, setUserId] = createSignal(1) const [status, setStatus] = createSignal('active') - // Good - all external values in deps - const { data } = useLiveQuery( - (q) => q.from({ todos: todosCollection }) - .where(({ todos }) => and( - eq(todos.userId, userId()), - eq(todos.status, status()) - )), - [userId, status] + // Solid automatically tracks userId() and status() calls + const query = useLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => and( + eq(todos.userId, userId()), + eq(todos.status, status()) + )) ) - // Bad - missing dependencies - const { data: badData } = useLiveQuery( - (q) => q.from({ todos: todosCollection }) - .where(({ todos }) => eq(todos.userId, userId())), - [] // Missing userId! + return ( +
+ +
{query.data.length} todos
+
) +} +``` + +**Key Point:** Unlike React, you don't need dependency arrays. Solid's reactive system automatically tracks any signals, props, or stores accessed during query execution. + +#### Best Practices + +**Access signals inside the query function:** + +```tsx +import { createSignal } from 'solid-js' +import { useLiveQuery } from '@tanstack/solid-db' +import { gt } from '@tanstack/db' + +function TodoList() { + const [minPriority, setMinPriority] = createSignal(5) - return
{data().length} todos
+ // Good - signal accessed inside query function + const query = useLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => gt(todos.priority, minPriority())) + ) + + // Solid automatically tracks minPriority() and recomputes when it changes + return
{query.data.length} todos
} ``` -**Empty array for static queries:** +**Don't read signals outside the query function:** ```tsx +import { createSignal } from 'solid-js' import { useLiveQuery } from '@tanstack/solid-db' +import { gt } from '@tanstack/db' -function AllTodos() { - // No external dependencies - query never changes - const { data } = useLiveQuery( - (q) => q.from({ todos: todosCollection }), - [] +function TodoList() { + const [minPriority, setMinPriority] = createSignal(5) + + // Bad - reading signal outside query function + const currentPriority = minPriority() + const query = useLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => gt(todos.priority, currentPriority)) ) + // Won't update when minPriority changes! - return
{data().length} todos
+ return
{query.data.length} todos
} ``` -**Omit the array for queries with no external dependencies:** +**Static queries need no special handling:** ```tsx import { useLiveQuery } from '@tanstack/solid-db' function AllTodos() { - // Same as above - no deps needed - const { data } = useLiveQuery( - (q) => q.from({ todos: todosCollection }) + // No signals accessed - query never changes + const query = useLiveQuery((q) => + q.from({ todos: todosCollection }) ) - return
{data().length} todos
+ return
{query.data.length} todos
+} +``` + +### Using Pre-created Collections + +You can also pass an existing collection to `useLiveQuery`. This is useful for sharing queries across components: + +```tsx +import { createLiveQueryCollection } from '@tanstack/db' +import { useLiveQuery } from '@tanstack/solid-db' + +// Create collection outside component +const todosQuery = createLiveQueryCollection((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => eq(todos.active, true)) +) + +function TodoList() { + // Pass existing collection + const query = useLiveQuery(() => todosQuery) + + return
{query.data.length} todos
} ``` diff --git a/docs/framework/vue/overview.md b/docs/framework/vue/overview.md index 9cb45017a..f4b2a3f6d 100644 --- a/docs/framework/vue/overview.md +++ b/docs/framework/vue/overview.md @@ -19,7 +19,7 @@ For comprehensive documentation on writing queries (filtering, joins, aggregatio ### useLiveQuery -The `useLiveQuery` composable creates a live query that automatically updates your component when data changes: +The `useLiveQuery` composable creates a live query that automatically updates your component when data changes. It returns reactive computed refs: ```vue @@ -68,7 +71,7 @@ const { data } = useLiveQuery( ``` -**Note:** When using props or refs in the query, wrap them in a function for the dependency array. +**Important:** Pass refs directly in the dependency array, not as functions. Vue will automatically track them. #### What Happens When Dependencies Change @@ -80,7 +83,7 @@ When a dependency value changes: #### Best Practices -**Include all external values used in the query:** +**Include all external refs used in the query:** ```vue + + +``` + +**Using with props:** + +```vue + + + ``` **Empty array for static queries:** @@ -122,6 +160,10 @@ const { data } = useLiveQuery( [] ) + + ``` **Omit the array for queries with no external dependencies:** @@ -135,4 +177,39 @@ const { data } = useLiveQuery( (q) => q.from({ todos: todosCollection }) ) + + +``` + +### Using Pre-created Collections + +You can also pass an existing collection to `useLiveQuery`. This is useful for sharing queries across components: + +```vue + + + ``` From 47c94277f088d65d8cae8bbc13a5f7dd3a54551d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Nov 2025 23:00:12 +0000 Subject: [PATCH 3/4] docs: fix Angular and Svelte framework overview issues Address critical issues identified in external code review: **Angular fixes:** - Replace invalid destructuring syntax ({ data } = injectLiveQuery) with correct field assignment (query = injectLiveQuery) - Update all templates to call signals with () as per Angular API - Add separate examples for Angular 16+ (@Input) vs 17+ (input.required) - Add note explaining all return values are Angular signals - Ensure all examples use query.data() and query.isLoading() **Svelte fixes:** - Remove incorrect $ prefix from all examples (not Svelte stores) - Change to const query = useLiveQuery() pattern - Update all templates to use query.data and query.isLoading directly - Add note explaining Svelte 5 runes return reactive values via getters - Ensure consistency: query.data (no call), query.isLoading (no call) These changes align documentation with actual adapter implementations and fix syntax errors that would cause compile failures. --- docs/framework/angular/overview.md | 69 ++++++++++++++++++++++-------- docs/framework/svelte/overview.md | 51 ++++++++++++++++------ 2 files changed, 90 insertions(+), 30 deletions(-) diff --git a/docs/framework/angular/overview.md b/docs/framework/angular/overview.md index d3539f7e8..cffa93371 100644 --- a/docs/framework/angular/overview.md +++ b/docs/framework/angular/overview.md @@ -19,7 +19,7 @@ For comprehensive documentation on writing queries (filtering, joins, aggregatio ### injectLiveQuery -The `injectLiveQuery` function creates a live query that automatically updates your component when data changes. It returns Angular signals for reactive state management: +The `injectLiveQuery` function creates a live query that automatically updates your component when data changes. It returns an object containing Angular signals for reactive state management: ```typescript import { Component } from '@angular/core' @@ -30,11 +30,11 @@ import { eq } from '@tanstack/db' selector: 'app-todo-list', standalone: true, template: ` - @if (isLoading()) { + @if (query.isLoading()) {
Loading...
} @else {
    - @for (todo of data(); track todo.id) { + @for (todo of query.data(); track todo.id) {
  • {{ todo.text }}
  • }
@@ -42,7 +42,7 @@ import { eq } from '@tanstack/db' ` }) export class TodoListComponent { - { data, isLoading } = injectLiveQuery((q) => + query = injectLiveQuery((q) => q.from({ todos: todosCollection }) .where(({ todos }) => eq(todos.completed, false)) .select(({ todos }) => ({ id: todos.id, text: todos.text })) @@ -50,6 +50,8 @@ export class TodoListComponent { } ``` +**Note:** All return values (`data`, `isLoading`, `status`, etc.) are Angular signals, so call them with `()` in your template: `query.data()`, `query.isLoading()`. + ### Reactive Parameters For queries that depend on reactive values, use the `params` option to re-run the query when those values change: @@ -63,13 +65,13 @@ import { gt } from '@tanstack/db' selector: 'app-filtered-todos', standalone: true, template: ` -
{{ data().length }} high-priority todos
+
{{ query.data().length }} high-priority todos
` }) export class FilteredTodosComponent { minPriority = signal(5) - { data } = injectLiveQuery({ + query = injectLiveQuery({ params: () => ({ minPriority: this.minPriority() }), query: ({ params, q }) => q.from({ todos: todosCollection }) @@ -100,6 +102,39 @@ When a parameter value changes: **Use reactive params for dynamic queries:** +```typescript +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: `
{{ query.data().length }} todos
` +}) +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) + )) + }) +} +``` + +**Using Angular 17+ signal inputs:** + ```typescript import { Component, input, signal } from '@angular/core' import { injectLiveQuery } from '@tanstack/angular-db' @@ -108,14 +143,14 @@ import { eq, and } from '@tanstack/db' @Component({ selector: 'app-todo-list', standalone: true, - template: `
{{ data().length }} todos
` + template: `
{{ query.data().length }} todos
` }) export class TodoListComponent { + // Angular 17+ signal-based input userId = input.required() status = signal('active') - // Good - reactive params track all dependencies - { data } = injectLiveQuery({ + query = injectLiveQuery({ params: () => ({ userId: this.userId(), status: this.status() @@ -139,17 +174,17 @@ import { injectLiveQuery } from '@tanstack/angular-db' @Component({ selector: 'app-all-todos', standalone: true, - template: `
{{ data().length }} todos
` + template: `
{{ query.data().length }} todos
` }) export class AllTodosComponent { // No reactive dependencies - query never changes - { data } = injectLiveQuery((q) => + query = injectLiveQuery((q) => q.from({ todos: todosCollection }) ) } ``` -**Access signals directly in template:** +**Access multiple signals in template:** ```typescript import { Component } from '@angular/core' @@ -160,14 +195,14 @@ import { eq } from '@tanstack/db' selector: 'app-todos', standalone: true, template: ` -
Status: {{ status() }}
-
Loading: {{ isLoading() }}
-
Ready: {{ isReady() }}
-
Total: {{ data().length }}
+
Status: {{ query.status() }}
+
Loading: {{ query.isLoading() }}
+
Ready: {{ query.isReady() }}
+
Total: {{ query.data().length }}
` }) export class TodosComponent { - { data, status, isLoading, isReady } = injectLiveQuery((q) => + query = injectLiveQuery((q) => q.from({ todos: todosCollection }) .where(({ todos }) => eq(todos.completed, false)) ) diff --git a/docs/framework/svelte/overview.md b/docs/framework/svelte/overview.md index 0adaed472..aeaa8cd95 100644 --- a/docs/framework/svelte/overview.md +++ b/docs/framework/svelte/overview.md @@ -19,31 +19,33 @@ For comprehensive documentation on writing queries (filtering, joins, aggregatio ### useLiveQuery -The `useLiveQuery` utility creates a live query that automatically updates your component when data changes: +The `useLiveQuery` utility creates a live query that automatically updates your component when data changes. It returns reactive values powered by Svelte 5 runes: ```svelte -{#if $isLoading} +{#if query.isLoading}
Loading...
{:else}
    - {#each $data as todo (todo.id)} + {#each query.data as todo (todo.id)}
  • {todo.text}
  • {/each}
{/if} ``` +**Note:** With Svelte 5, `useLiveQuery` returns reactive values through getters. Access `query.data` and `query.isLoading` directly (no `$` prefix needed). + ### Dependency Arrays The `useLiveQuery` utility accepts an optional dependency array as its last parameter. When any value in the array changes, the query is recreated and re-executed. @@ -59,14 +61,14 @@ Use dependency arrays when your query depends on external reactive values (props let { minPriority } = $props() - const { data } = useLiveQuery( + const query = useLiveQuery( (q) => q.from({ todos: todosCollection }) .where(({ todos }) => gt(todos.priority, minPriority)), [() => minPriority] // Re-run when minPriority changes ) -
{$data.length} high-priority todos
+
{query.data.length} high-priority todos
``` **Note:** When using props or reactive state in the query, wrap them in a function for the dependency array. @@ -92,7 +94,7 @@ When a dependency value changes: let status = $state('active') // Good - all external values in deps - const { data } = useLiveQuery( + const query = useLiveQuery( (q) => q.from({ todos: todosCollection }) .where(({ todos }) => and( eq(todos.userId, userId), @@ -102,14 +104,14 @@ When a dependency value changes: ) // Bad - missing dependencies - const { data: badData } = useLiveQuery( + const badQuery = useLiveQuery( (q) => q.from({ todos: todosCollection }) .where(({ todos }) => eq(todos.userId, userId)), [] // Missing userId! ) -
{$data.length} todos
+
{query.data.length} todos
``` **Empty array for static queries:** @@ -119,13 +121,13 @@ When a dependency value changes: import { useLiveQuery } from '@tanstack/svelte-db' // No external dependencies - query never changes - const { data } = useLiveQuery( + const query = useLiveQuery( (q) => q.from({ todos: todosCollection }), [] ) -
{$data.length} todos
+
{query.data.length} todos
``` **Omit the array for queries with no external dependencies:** @@ -135,10 +137,33 @@ When a dependency value changes: import { useLiveQuery } from '@tanstack/svelte-db' // Same as above - no deps needed - const { data } = useLiveQuery( + const query = useLiveQuery( (q) => q.from({ todos: todosCollection }) ) -
{$data.length} todos
+
{query.data.length} todos
+``` + +### Accessing Multiple Properties + +You can access all status properties directly on the query result: + +```svelte + + +
+
Status: {query.status}
+
Loading: {query.isLoading}
+
Ready: {query.isReady}
+
Total: {query.data.length}
+
``` From 6d397549ae0b8ab2c764254e572f31e4a7445884 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Nov 2025 23:24:54 +0000 Subject: [PATCH 4/4] docs: address second-round reviewer feedback on Angular and Solid Apply precision improvements from external code review: **Angular:** - Soften parameter-change behavior wording to avoid over-promising timing guarantees (changed from "isLoading becomes true" to "status()/isLoading() reflect the new query's lifecycle") - Add template syntax version note explaining @if/@for requires Angular 17+ (v16 users should use *ngIf/*ngFor) **Solid:** - Fix contradictory intro sentence that claimed "all return values should be called as functions" while the note correctly stated "data is a plain array" - Now states clearly: "data is a plain array and status fields are accessors" All changes align documentation with exact adapter behavior and prevent user confusion about API contracts. --- docs/framework/angular/overview.md | 8 +++++--- docs/framework/solid/overview.md | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/framework/angular/overview.md b/docs/framework/angular/overview.md index cffa93371..15adcaf6c 100644 --- a/docs/framework/angular/overview.md +++ b/docs/framework/angular/overview.md @@ -52,6 +52,8 @@ export class TodoListComponent { **Note:** All return values (`data`, `isLoading`, `status`, etc.) are Angular signals, so call them with `()` in your template: `query.data()`, `query.isLoading()`. +> **Template Syntax:** Examples use Angular 17+ control flow (`@if`, `@for`). For Angular 16, use `*ngIf` and `*ngFor` instead. + ### Reactive Parameters For queries that depend on reactive values, use the `params` option to re-run the query when those values change: @@ -93,10 +95,10 @@ When any reactive value accessed in the `params` function changes, the query is #### What Happens When Parameters Change When a parameter value changes: -1. The previous live query collection is cleaned up +1. The previous live-query collection is disposed 2. A new query is created with the updated parameter values -3. The component updates automatically through Angular's signals -4. The `isLoading` signal becomes `true` until the new data is ready +3. `status()`/`isLoading()` reflect the new query's lifecycle +4. `data()` updates automatically when the new results arrive #### Best Practices diff --git a/docs/framework/solid/overview.md b/docs/framework/solid/overview.md index d9a90854b..d7781bfbc 100644 --- a/docs/framework/solid/overview.md +++ b/docs/framework/solid/overview.md @@ -19,7 +19,7 @@ For comprehensive documentation on writing queries (filtering, joins, aggregatio ### useLiveQuery -The `useLiveQuery` primitive creates a live query that automatically updates your component when data changes. All return values are reactive and should be called as functions: +The `useLiveQuery` primitive creates a live query that automatically updates your component when data changes. It returns an object where `data` is a plain array and status fields (e.g. `isLoading()`, `status()`) are accessors: ```tsx import { useLiveQuery } from '@tanstack/solid-db'