Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/chubby-wasps-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/preact-form': patch
---

Initial release of Preact adapter
Comment on lines +2 to +5
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Changeset entry =="
rg -n "'@tanstack/preact-form': (patch|minor|major)" .changeset/chubby-wasps-fry.md

echo
echo "== Package manifest =="
fd -i "package.json" packages --exec sh -c '
  for f in "$@"; do
    if rg -q "\"name\"\\s*:\\s*\"@tanstack/preact-form\"" "$f"; then
      echo "Found: $f"
      sed -n "1,120p" "$f"
    fi
  done
' sh {}

echo
echo "== npm registry publish status =="
curl -s https://registry.npmjs.org/@tanstack%2fpreact-form | jq '."dist-tags".latest // "UNPUBLISHED"'

Repository: TanStack/form

Length of output: 2092


Update the changelog to reflect this is not an initial release.

The package @tanstack/preact-form is already published on npm (version 0.0.1) and currently at version 1.29.3 locally. The changelog on line 5 stating "Initial release of Preact adapter" is inaccurate. Revise it to describe the actual changes in this patch update (e.g., "Fixed X" or "Improved Y" depending on what this patch contains).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/chubby-wasps-fry.md around lines 2 - 5, Replace the incorrect
"Initial release of Preact adapter" entry in the changeset for
'@tanstack/preact-form' with an accurate one-line summary of what this patch
does (e.g., "Fixed X", "Improved Y", or "Compatibility fix for v1.29.3"); locate
the sentence "Initial release of Preact adapter" in the .changeset content and
edit it to succinctly describe the actual patch changes so the changelog
reflects this is not an initial release.

99 changes: 99 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@
}
]
},
{
"label": "preact",
"children": [
{
"label": "Quick Start",
"to": "framework/preact/quick-start"
}
]
},
{
"label": "vue",
"children": [
Expand Down Expand Up @@ -169,6 +178,67 @@
}
]
},
{
"label": "preact",
"children": [
{
"label": "Basic Concepts",
"to": "framework/preact/guides/basic-concepts"
},
{
"label": "Form Validation",
"to": "framework/preact/guides/validation"
},
{
"label": "Dynamic Validation",
"to": "framework/preact/guides/dynamic-validation"
},
{
"label": "Async Initial Values",
"to": "framework/preact/guides/async-initial-values"
},
{
"label": "Arrays",
"to": "framework/preact/guides/arrays"
},
{
"label": "Linked Fields",
"to": "framework/preact/guides/linked-fields"
},
{
"label": "Reactivity",
"to": "framework/preact/guides/reactivity"
},
{
"label": "Listeners",
"to": "framework/preact/guides/listeners"
},
{
"label": "Custom Errors",
"to": "framework/preact/guides/custom-errors"
},
{
"label": "Submission Handling",
"to": "framework/preact/guides/submission-handling"
},
{
"label": "UI Libraries",
"to": "framework/preact/guides/ui-libraries"
},
{
"label": "Focus Management",
"to": "framework/preact/guides/focus-management"
},
{
"label": "Form Composition",
"to": "framework/preact/guides/form-composition"
},
{
"label": "Debugging",
"to": "framework/preact/guides/debugging"
}
]
},
{
"label": "vue",
"children": [
Expand Down Expand Up @@ -436,6 +506,35 @@
}
]
},
{
"label": "preact",
"children": [
{
"label": "Preact Reference",
"to": "framework/preact/reference/index"
},
{
"label": "Variables / Field",
"to": "framework/preact/reference/variables/Field"
},
{
"label": "Functions / useField",
"to": "framework/preact/reference/functions/useField"
},
{
"label": "Functions / useForm",
"to": "framework/preact/reference/functions/useForm"
},
{
"label": "Types / FieldComponent",
"to": "framework/preact/reference/type-aliases/FieldComponent"
},
{
"label": "Types / UseField",
"to": "framework/preact/reference/type-aliases/UseField"
}
]
},
{
"label": "vue",
"children": [
Expand Down
14 changes: 7 additions & 7 deletions docs/framework/angular/guides/arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ This will generate the mapped JSX every time you run `pushValue` on `field`:
Finally, you can use a subfield like so:

```angular-html
<ng-container
<ng-container
[tanstackField]="form"
[name]="getPeopleName($index)"
#person="field"
Expand All @@ -57,9 +57,7 @@ Finally, you can use a subfield like so:
<div>Name for person {{ $index }}</div>
<input
[value]="person.api.state.value"
(input)="
person.api.handleChange($any($event).target.value)
"
(input)="person.api.handleChange($any($event).target.value)"
/>
</label>
</div>
Expand All @@ -81,7 +79,10 @@ export class AppComponent {
> See, if we did the following:
>
> ```angular-html
> <ng-container [tanstackField]="form" [name]="'people[' + $index + '].name'"></ng-container>
> <ng-container
> [tanstackField]="form"
> [name]="'people[' + $index + '].name'"
> ></ng-container>
> ```
>
> We'd be running into a TypeScript issue where `"one" + "two"` is `string` rather than the required `"onetwo"` type
Expand Down Expand Up @@ -145,8 +146,7 @@ export class AppComponent {
},
})


getPeopleName = (idx: number) => `people[${idx}].name` as const;
getPeopleName = (idx: number) => `people[${idx}].name` as const

canSubmit = injectStore(this.form, (state) => state.canSubmit)
isSubmitting = injectStore(this.form, (state) => state.isSubmitting)
Expand Down
21 changes: 10 additions & 11 deletions docs/framework/angular/guides/basic-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,20 +121,19 @@ Example:
`,
})
export class AppComponent {
firstNameValidator: FieldValidateFn<any, any, string, any> = ({
value,
}) =>
firstNameValidator: FieldValidateFn<any, any, string, any> = ({ value }) =>
!value
? 'A first name is required'
: value.length < 3
? 'First name must be at least 3 characters'
: undefined

firstNameAsyncValidator: FieldValidateAsyncFn<any, string, any> =
async ({ value }) => {
await new Promise((resolve) => setTimeout(resolve, 1000))
return value.includes('error') && 'No "error" allowed in first name'
}
firstNameAsyncValidator: FieldValidateAsyncFn<any, string, any> = async ({
value,
}) => {
await new Promise((resolve) => setTimeout(resolve, 1000))
return value.includes('error') && 'No "error" allowed in first name'
}

form = injectForm({
defaultValues: {
Expand Down Expand Up @@ -176,7 +175,7 @@ import { z } from 'zod'
[validators]="{
onChange: z.string().min(3, 'First name must be at least 3 characters'),
onChangeAsyncDebounceMs: 500,
onChangeAsync: firstNameAsyncValidator
onChangeAsync: firstNameAsyncValidator,
}"
#firstName="field"
>
Expand Down Expand Up @@ -343,8 +342,8 @@ export class AppComponent {
yearsOfExperience: 0,
}

getHobbyName = (idx: number) => `hobbies[${idx}].name` as const;
getHobbyDesc = (idx: number) => `hobbies[${idx}].description` as const;
getHobbyName = (idx: number) => `hobbies[${idx}].name` as const
getHobbyDesc = (idx: number) => `hobbies[${idx}].description` as const

form = injectForm({
defaultValues: {
Expand Down
60 changes: 38 additions & 22 deletions docs/framework/angular/guides/dynamic-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ We support this through our `onDynamic` validation function.

```angular-ts
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
import {
TanStackField,
injectForm,
revalidateLogic,
} from '@tanstack/angular-form'

@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
template: ` <!-- Your form template here --> `,
})
export class AppComponent {
form = injectForm({
Expand Down Expand Up @@ -65,9 +67,7 @@ You can, for example, use the following to revalidate on blur after the first su
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
template: ` <!-- Your form template here --> `,
})
export class AppComponent {
form = injectForm({
Expand All @@ -87,15 +87,18 @@ Just as you might access errors from an `onChange` or `onBlur` validation, you c

```angular-ts
import { Component } from '@angular/core'
import { TanStackField, injectForm, injectStore, revalidateLogic } from '@tanstack/angular-form'
import {
TanStackField,
injectForm,
injectStore,
revalidateLogic,
} from '@tanstack/angular-form'

@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<p>{{ formErrorMap().onDynamic?.firstName }}</p>
`,
template: ` <p>{{ formErrorMap().onDynamic?.firstName }}</p> `,
})
export class AppComponent {
form = injectForm({
Expand All @@ -121,7 +124,12 @@ You can use `onDynamic` validation alongside other validation logic, such as `on

```angular-ts
import { Component } from '@angular/core'
import { TanStackField, injectForm, injectStore, revalidateLogic } from '@tanstack/angular-form'
import {
TanStackField,
injectForm,
injectStore,
revalidateLogic,
} from '@tanstack/angular-form'

@Component({
selector: 'app-root',
Expand Down Expand Up @@ -167,7 +175,11 @@ You can also use `onDynamic` validation with fields, just like you would with ot

```angular-ts
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
import {
TanStackField,
injectForm,
revalidateLogic,
} from '@tanstack/angular-form'
import type { FieldValidateFn } from '@tanstack/angular-form'

@Component({
Expand All @@ -180,7 +192,7 @@ import type { FieldValidateFn } from '@tanstack/angular-form'
[tanstackField]="form"
name="age"
[validators]="{
onDynamic: ageValidator
onDynamic: ageValidator,
}"
#age="field"
>
Expand Down Expand Up @@ -229,15 +241,17 @@ Async validation can also be used with `onDynamic` just like with other validati

```angular-ts
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
import {
TanStackField,
injectForm,
revalidateLogic,
} from '@tanstack/angular-form'

@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
template: ` <!-- Your form template here --> `,
})
export class AppComponent {
form = injectForm({
Expand Down Expand Up @@ -266,16 +280,18 @@ You can also use standard schema validation libraries like Valibot or Zod with `

```angular-ts
import { Component } from '@angular/core'
import { TanStackField, injectForm, revalidateLogic } from '@tanstack/angular-form'
import {
TanStackField,
injectForm,
revalidateLogic,
} from '@tanstack/angular-form'
import { z } from 'zod'

@Component({
selector: 'app-root',
standalone: true,
imports: [TanStackField],
template: `
<!-- Your form template here -->
`,
template: ` <!-- Your form template here --> `,
})
export class AppComponent {
schema = z.object({
Expand Down
14 changes: 3 additions & 11 deletions docs/framework/angular/guides/form-composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ import { TanStackField, injectForm, injectStore } from '@tanstack/angular-form'
imports: [TanStackField],
template: `
<div>
<ng-container
[tanstackField]="form"
name="firstName"
#firstName="field"
>
<ng-container [tanstackField]="form" name="firstName" #firstName="field">
<label [for]="firstName.api.name">First Name:</label>
<input
[id]="firstName.api.name"
Expand All @@ -47,11 +43,7 @@ import { TanStackField, injectForm, injectStore } from '@tanstack/angular-form'
</ng-container>
</div>
<div>
<ng-container
[tanstackField]="form"
name="lastName"
#lastName="field"
>
<ng-container [tanstackField]="form" name="lastName" #lastName="field">
<label [for]="lastName.api.name">Last Name:</label>
<input
[id]="lastName.api.name"
Expand Down Expand Up @@ -91,7 +83,7 @@ export class AppComponent {
This is functionally correct, but introduces a _lot_ of repeated templating behavior over and over. Instead, let's move the error handling, label to input binding, and other repeated logic into a component:

```angular-ts
import {injectField} from '@tanstack/angular-form'
import { injectField } from '@tanstack/angular-form'

@Component({
selector: 'app-text-field',
Expand Down
Loading
Loading