diff --git a/docs/framework/angular/overview.md b/docs/framework/angular/overview.md index d4b911614..15adcaf6c 100644 --- a/docs/framework/angular/overview.md +++ b/docs/framework/angular/overview.md @@ -13,4 +13,200 @@ 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 an object containing 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 (query.isLoading()) { +
Loading...
+ } @else { + + } + ` +}) +export class TodoListComponent { + query = injectLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => eq(todos.completed, false)) + .select(({ todos }) => ({ id: todos.id, text: todos.text })) + ) +} +``` + +**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: + +```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: ` +
{{ query.data().length }} high-priority todos
+ ` +}) +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 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 disposed +2. A new query is created with the updated parameter values +3. `status()`/`isLoading()` reflect the new query's lifecycle +4. `data()` updates automatically when the new results arrive + +#### 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: `
{{ 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' +import { eq, and } from '@tanstack/db' + +@Component({ + selector: 'app-todo-list', + standalone: true, + template: `
{{ query.data().length }} todos
` +}) +export class TodoListComponent { + // Angular 17+ signal-based input + userId = input.required() + 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) + )) + }) +} +``` + +**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: `
{{ query.data().length }} todos
` +}) +export class AllTodosComponent { + // No reactive dependencies - query never changes + query = injectLiveQuery((q) => + q.from({ todos: todosCollection }) + ) +} +``` + +**Access multiple signals 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: {{ query.status() }}
+
Loading: {{ query.isLoading() }}
+
Ready: {{ query.isReady() }}
+
Total: {{ query.data().length }}
+ ` +}) +export class TodosComponent { + query = 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..d7781bfbc 100644 --- a/docs/framework/solid/overview.md +++ b/docs/framework/solid/overview.md @@ -1,5 +1,189 @@ --- 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. 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' +import { eq } from '@tanstack/db' +import { Show, For } from 'solid-js' + +function TodoList() { + const query = useLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => eq(todos.completed, false)) + .select(({ todos }) => ({ id: todos.id, text: todos.text })) + ) + + return ( + Loading...}> + + + ) +} +``` + +**Note:** `query.data` returns an array directly (not a function), but status fields like `isLoading()`, `status()`, etc. are accessor functions. + +### Reactive Queries with 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 query = useLiveQuery((q) => + q.from({ todos: todosCollection }) + .where(({ todos }) => gt(todos.priority, props.minPriority)) + ) + + return
{query.data.length} high-priority todos
+} +``` + +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 + +#### Using Signals from Component State + +```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') + + // 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()) + )) + ) + + 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) + + // 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
+} +``` + +**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 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
{query.data.length} todos
+} +``` + +**Static queries need no special handling:** + +```tsx +import { useLiveQuery } from '@tanstack/solid-db' + +function AllTodos() { + // No signals accessed - query never changes + const query = useLiveQuery((q) => + q.from({ todos: todosCollection }) + ) + + 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/svelte/overview.md b/docs/framework/svelte/overview.md index 079ec6d9b..aeaa8cd95 100644 --- a/docs/framework/svelte/overview.md +++ b/docs/framework/svelte/overview.md @@ -1,5 +1,169 @@ --- 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. It returns reactive values powered by Svelte 5 runes: + +```svelte + + +{#if query.isLoading} +
Loading...
+{:else} + +{/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. + +#### When to Use Dependency Arrays + +Use dependency arrays when your query depends on external reactive values (props or state): + +```svelte + + +
{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. + +#### 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 + + +
{query.data.length} todos
+``` + +**Empty array for static queries:** + +```svelte + + +
{query.data.length} todos
+``` + +**Omit the array for queries with no external dependencies:** + +```svelte + + +
{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}
+
+``` diff --git a/docs/framework/vue/overview.md b/docs/framework/vue/overview.md index 533fc7a2e..f4b2a3f6d 100644 --- a/docs/framework/vue/overview.md +++ b/docs/framework/vue/overview.md @@ -1,5 +1,215 @@ --- 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. It returns reactive computed refs: + +```vue + + + +``` + +**Note:** All return values (`data`, `isLoading`, `status`, etc.) are computed refs, so access them with `.value` in ` + + +``` + +**Important:** Pass refs directly in the dependency array, not as functions. Vue will automatically track them. + +#### 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 refs used in the query:** + +```vue + + + +``` + +**Using with props:** + +```vue + + + +``` + +**Empty array for static queries:** + +```vue + + + +``` + +**Omit the array for queries with no external dependencies:** + +```vue + + + +``` + +### Using Pre-created Collections + +You can also pass an existing collection to `useLiveQuery`. This is useful for sharing queries across components: + +```vue + + + +```