Skip to content

Add @formisch/angular package with playground#124

Open
fabian-hiller wants to merge 29 commits into
mainfrom
feat/angular-package
Open

Add @formisch/angular package with playground#124
fabian-hiller wants to merge 29 commits into
mainfrom
feat/angular-package

Conversation

@fabian-hiller

@fabian-hiller fabian-hiller commented May 31, 2026

Copy link
Copy Markdown
Member

Implements the full Angular framework package for Formisch (@formisch/angular): types, injectForm / injectField / injectFieldArray, the FormischForm / FormischField / FormischFieldArray components, and a playground with full parity to the other framework playgrounds.

Highlights

  • Signal-based APIinjectForm, injectField, and injectFieldArray expose reactive Angular signals; the components are thin wrappers that delegate to them.
  • Self-contained published packagengc (partial Ivy) compiles the components, then rolldown bundles @formisch/core and @formisch/methods into dist (no @formisch/* runtime deps, matching the other frameworks), keeping @angular/* and valibot as peer dependencies.
  • Playground — login, payment, todos, special and nested routes, matching the Solid playground 1:1 (including the expandable error-freeze animation), with strictTemplates enabled for type-safe field paths.
  • All checks green: 40 unit + type tests, lint, build, and format.

Closes #111.

🤖 Generated with Claude Code


Summary by cubic

Adds the Angular package @formisch/angular with a signal-based API, standalone directives, a full playground, and CI. Upgrades to Angular 22 with zoneless-safe fixes (event handling and async submit tracking) and ships a self-contained ngc + rolldown build.

  • New Features

    • APIs: injectForm, injectField, injectFieldArray return Angular signals; types: FormStore, FieldStore, FieldArrayStore.
    • Directives: FormischForm (disables native validation, registers form, emits formischSubmit, integrates handleSubmit, focuses first invalid), FormischField / FormischFieldArray (structural, typed via of), FormischControl (binds inputs/changes/focus/blur, registers element). AOT- and zoneless-safe.
    • Build: compile with ngc (partial Ivy) then bundle via rolldown; inline @formisch/core/@formisch/methods via ./angular entries; keep @angular/* and valibot as peers.
    • Playground: login, payment, todos, special, nested; shared UI; custom AutoAnimateDirective; improved semantics and animations.
  • Dependencies

    • @formisch/methods: add ./angular export and build target; add optional peer @angular/core.
    • Angular to v22; framework/playground use typescript ~6.0.3 (root stays ~5.9.3); valibot to ^1.4.1.
    • CI: add Prettier, ESLint, and Vitest jobs for frameworks/angular.
    • Prettier: enable decorators-legacy and restore jsx parser plugin.

Written for commit 94291b6. Summary will update on new commits.

Review in cubic

sonukapoor and others added 18 commits May 30, 2026 23:45
- Fix FormischFieldArray to use signal inputs and contentChild() for AOT compatibility
- Replace @formkit/auto-animate/angular (no Ivy metadata) with a custom AutoAnimateDirective using afterNextRender
- Fix (change) → (input) on text-input and slider so validate: 'input' fires on every keystroke
- Replace effect + setTimeout pattern in ExpandableComponent with afterRenderEffect
- Add nested and special playground routes matching React 1:1
- Add all shared UI components (checkbox, select, radio, slider, file-input, expandable, etc.)
- Bind [value] on <select> element for controlled component behavior instead of [selected] on each option; remove now-unused isSelected() method
- Wrap await handler() in try/finally in UnstyledButtonComponent so isLoading resets even when the handler throws
Copilot AI review requested due to automatic review settings May 31, 2026 03:47
@vercel

vercel Bot commented May 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
formisch Error Error Jun 6, 2026 11:58pm

Request Review

@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. enhancement New feature or request labels May 31, 2026
@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This pull request introduces a complete Angular integration for Formisch, including a new @formisch/angular npm package, comprehensive TypeScript support with generic typing for form and field stores, Angular-specific directives for template binding, injection-based helpers for creating reactive form and field instances, a Vitest test suite covering types and runtime behavior, and a fully functional Angular playground application demonstrating form handling across multiple pages with login, payment processing, todo lists, special input types, and nested array manipulation.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 69baea5a8b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frameworks/angular/src/functions/injectField/injectField.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds the new @formisch/angular framework package (signals-based API + headless components) and an Angular playground to bring Angular to parity with the other framework integrations, alongside build/tooling updates to support decorators and Angular-specific method exports.

Changes:

  • Introduces @formisch/angular package with injectForm / injectField / injectFieldArray, component wrappers, and supporting types/utils/tests.
  • Adds an Angular playground app (Vite + Analog Angular plugin) with routes matching the other framework playgrounds.
  • Extends @formisch/methods to ship an ./angular entry and updates Prettier import-sorting parser plugins for decorator syntax.

Reviewed changes

Copilot reviewed 81 out of 84 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
prettier.config.js Enables decorator-aware parsing for import sorting.
.gitignore Ignores an additional generated docs path.
packages/methods/tsdown.config.ts Adds Angular as a build target for methods.
packages/methods/package.json Exposes @formisch/methods/angular export + Angular peer metadata.
frameworks/angular/package.json New publishable @formisch/angular package configuration and scripts.
frameworks/angular/rolldown.config.ts Bundling config to inline internal packages and keep Angular/valibot external.
frameworks/angular/eslint.config.ts Angular package lint configuration.
frameworks/angular/tsconfig.json Base TS config for Angular package.
frameworks/angular/tsconfig.build.json Build TS + Angular compiler settings (partial Ivy).
frameworks/angular/tsconfig.spec.json Test TS config for Vitest.
frameworks/angular/vitest.config.ts Vitest setup for Angular package (jsdom + typecheck + coverage).
frameworks/angular/CHANGELOG.md New changelog scaffold for the Angular package.
frameworks/angular/src/index.ts Public entrypoint re-exporting core/methods + Angular-specific APIs/components.
frameworks/angular/src/types/index.ts Aggregates Angular framework package types.
frameworks/angular/src/types/form.ts Defines FormStore shape for Angular signals.
frameworks/angular/src/types/field.ts Defines FieldStore / FieldArrayStore and element prop types.
frameworks/angular/src/types/utils.ts Adds SignalOrValue helper type.
frameworks/angular/src/utils/index.ts Aggregates framework utilities.
frameworks/angular/src/utils/readSignalOrValue/index.ts Utility barrel export.
frameworks/angular/src/utils/readSignalOrValue/readSignalOrValue.ts Implements reading either a value or a signal.
frameworks/angular/src/utils/readSignalOrValue/readSignalOrValue.test.ts Unit tests for readSignalOrValue.
frameworks/angular/src/functions/index.ts Aggregates injectable APIs.
frameworks/angular/src/functions/injectForm/index.ts Barrel export for injectForm.
frameworks/angular/src/functions/injectForm/injectForm.ts Implements Angular injection-context form store creator.
frameworks/angular/src/functions/injectForm/injectForm.test.ts Runtime tests for injectForm.
frameworks/angular/src/functions/injectForm/injectForm.test-d.ts Type-level tests for injectForm.
frameworks/angular/src/functions/injectField/index.ts Barrel export for injectField.
frameworks/angular/src/functions/injectField/injectField.ts Implements field store injection + event handlers.
frameworks/angular/src/functions/injectField/injectField.test.ts Runtime tests for injectField.
frameworks/angular/src/functions/injectField/injectField.test-d.ts Type-level tests for injectField.
frameworks/angular/src/functions/injectFieldArray/index.ts Barrel export for injectFieldArray.
frameworks/angular/src/functions/injectFieldArray/injectFieldArray.ts Implements field-array store injection.
frameworks/angular/src/functions/injectFieldArray/injectFieldArray.test.ts Runtime tests for injectFieldArray.
frameworks/angular/src/functions/injectFieldArray/injectFieldArray.test-d.ts Type-level tests for injectFieldArray.
frameworks/angular/src/components/index.ts Aggregates Angular wrapper components.
frameworks/angular/src/components/FormischForm/index.ts Barrel export for FormischForm.
frameworks/angular/src/components/FormischForm/FormischForm.ts Wrapper component around native <form> + submission handling.
frameworks/angular/src/components/FormischForm/FormischForm.test.ts Dist-level component test for FormischForm.
frameworks/angular/src/components/FormischField/index.ts Barrel export for FormischField.
frameworks/angular/src/components/FormischField/FormischField.ts Headless field component providing store via template context.
frameworks/angular/src/components/FormischField/FormischField.test.ts Dist-level component test for FormischField.
frameworks/angular/src/components/FormischFieldArray/index.ts Barrel export for FormischFieldArray.
frameworks/angular/src/components/FormischFieldArray/FormischFieldArray.ts Headless field-array component providing store via template context.
frameworks/angular/src/components/FormischFieldArray/FormischFieldArray.test.ts Dist-level component test for FormischFieldArray.
frameworks/angular/src/vitest/setup.ts Angular TestBed initialization for Vitest.
frameworks/angular/src/vitest/loadDistComponent.ts Helper to import compiled components from dist during tests.
playgrounds/angular/package.json Adds Angular playground package (Vite + Angular deps).
playgrounds/angular/vite.config.ts Vite config for Angular playground + local alias to framework source.
playgrounds/angular/index.html Playground HTML shell.
playgrounds/angular/tsconfig.json TS project references for playground.
playgrounds/angular/tsconfig.app.json Playground compiler options + strict templates.
playgrounds/angular/src/main.ts Bootstraps Angular application.
playgrounds/angular/src/app.config.ts App providers including zoneless change detection + router.
playgrounds/angular/src/app.routes.ts Lazy route configuration for playground pages.
playgrounds/angular/src/app.component.ts Root component w/ tab navigation + indicator.
playgrounds/angular/src/global.css Tailwind + font + global styles.
playgrounds/angular/src/utils/disable-transitions.ts Utility for temporarily disabling transitions.
playgrounds/angular/src/icons/angle-down-icon.component.ts SVG icon used in the select component.
playgrounds/angular/src/components/action-button.component.ts Styled button wrapper.
playgrounds/angular/src/components/unstyled-button.component.ts Base button w/ loading state and spinner.
playgrounds/angular/src/components/spinner.component.ts Spinner element used during loading.
playgrounds/angular/src/components/button-group.component.ts Simple layout component for grouping buttons.
playgrounds/angular/src/components/color-button.component.ts Demo button component with color variants.
playgrounds/angular/src/components/input-label.component.ts Shared input label rendering utility.
playgrounds/angular/src/components/input-errors.component.ts Animated input error display with “frozen” message.
playgrounds/angular/src/components/expandable.component.ts Expand/collapse wrapper used for animated error rendering.
playgrounds/angular/src/components/text-input.component.ts Text input component used across routes.
playgrounds/angular/src/components/slider.component.ts Range slider input component.
playgrounds/angular/src/components/select.component.ts Select/multi-select input component.
playgrounds/angular/src/components/radio.component.ts Single radio input component.
playgrounds/angular/src/components/radio-group.component.ts Radio group component with options.
playgrounds/angular/src/components/checkbox.component.ts Checkbox input component.
playgrounds/angular/src/components/file-input.component.ts File input component with display text.
playgrounds/angular/src/components/form-header.component.ts Playground form header + reset/submit buttons.
playgrounds/angular/src/components/form-footer.component.ts Playground form footer + reset/submit buttons.
playgrounds/angular/src/components/form-error.component.ts Playground form-level error display.
playgrounds/angular/src/components/auto-animate.directive.ts Directive enabling auto-animate on host elements.
playgrounds/angular/src/routes/login/login.component.ts Login form route demonstrating basic fields/validation.
playgrounds/angular/src/routes/payment/payment.component.ts Payment form route demonstrating schema variants.
playgrounds/angular/src/routes/todos/todos.component.ts Todos route demonstrating field arrays + array methods.
playgrounds/angular/src/routes/special/special.component.ts Special inputs route (checkboxes, radios, selects, files, sliders).
playgrounds/angular/src/routes/nested/nested.component.ts Nested arrays route demonstrating deep path handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frameworks/angular/src/types/utils.ts
Comment thread packages/methods/package.json
Comment thread frameworks/angular/CHANGELOG.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (1)
playgrounds/angular/src/routes/todos/todos.component.ts (1)

209-225: ⚡ Quick win

Field-array helpers already no-op on out-of-bounds indices; guards aren’t necessary
move, swap, and replace each check that the provided indices fall within 0..items.length-1 (and move/swap also require indices to differ). When todos is empty or too short, the helpers skip the mutation entirely, so the handlers won’t hit invalid children[...] accesses. Optional: disable/hide the “Move first to end” / “Swap first two” / “Replace first” buttons when fieldArray.items().length is too small to avoid confusing no-op clicks.

🤖 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 `@playgrounds/angular/src/routes/todos/todos.component.ts` around lines 209 -
225, The handlers handleMoveFirstToEnd, handleSwapFirstTwo, and
handleReplaceFirst currently guard against out-of-bounds indices even though the
field-array helpers move, swap, and replace already no-op for invalid indices;
remove any redundant index-guarding code around these handlers so they call
move/swap/replace directly (as shown) and optionally disable or hide the UI
buttons when fieldArray.items().length is too small to avoid confusing no-op
clicks.
🤖 Prompt for all review comments with 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.

Inline comments:
In `@frameworks/angular/CHANGELOG.md`:
- Line 5: Update the release header "## v0.0.1 (Month DD, YYYY)" in the
CHANGELOG entry to the actual release date (e.g., "## v0.0.1 (2026-05-31)" or
match the project's existing date format), replacing the placeholder text;
ensure the date format is consistent with other changelog entries and commit the
change with a clear message like "chore(changelog): set v0.0.1 release date".

In `@playgrounds/angular/package.json`:
- Line 20: The playground's dependency entry "valibot": "^1.2.0" does not match
the Angular framework's peer dependency range ("valibot": "^1.4.1"); update the
playground dependency for the "valibot" key from ^1.2.0 to ^1.4.1 so the
dependency graph and peer resolution align with the framework's
peerDependencies.

In `@playgrounds/angular/src/app.config.ts`:
- Around line 1-13: Replace the experimental API with the stable one: update the
import to use provideZonelessChangeDetection from '`@angular/core`' (replace
provideExperimentalZonelessChangeDetection) and call
provideZonelessChangeDetection() in the appConfig.providers array instead of
provideExperimentalZonelessChangeDetection(); ensure the symbol replacement is
done both in the import list and where appConfig is defined so providers
contains provideZonelessChangeDetection() alongside provideRouter(routes).

In `@playgrounds/angular/src/components/file-input.component.ts`:
- Around line 31-33: The aria-errormessage attribute is always set; update the
[attr.aria-errormessage] binding so it only returns the error-id when errors()
is truthy and returns null/undefined otherwise (so the attribute is removed when
there are no errors); locate the binding on the element using errors() and
name() in file-input.component.ts and change the expression that computes
aria-errormessage to conditionally derive name() + '-error' only when errors()
exists.

In `@playgrounds/angular/src/components/input-label.component.ts`:
- Around line 20-35: The template currently prioritizes name() over component(),
causing component="div" to be ignored; update the branching in
input-label.component.ts so you explicitly check component() === 'div' before
falling back to the name() branch (i.e., handle component() === 'legend' first,
then component() === 'div', then name(), otherwise default), ensuring the div
branch renders even when name() is truthy; look for the component(), name(),
labelClass, label(), and required() usages to adjust the conditional order.

In `@playgrounds/angular/src/global.css`:
- Line 5: The CSS font-family declaration uses quoted identifier "'Lexend'"
which violates the font-family-name-quotes Stylelint rule; update the
declaration(s) (the "font-family: 'Lexend';" occurrences) to use an unquoted
identifier (e.g., change to font-family: Lexend;) and ensure any other similar
occurrences (notably the second instance mentioned) are fixed the same way,
leaving quotes only for multi-word font names or when required.

In `@playgrounds/angular/src/routes/nested/nested.component.ts`:
- Around line 223-260: The move/swap/replace functions (moveItemFirstToEnd,
swapItemsFirstTwo, replaceFirst, moveOptionFirstToEnd, swapOptionsFirstTwo) can
be called with empty or too-short arrays and produce invalid indices; add guards
that check the target array lengths before calling these helpers (e.g., only
call moveItemFirstToEnd or replaceFirst when items.length > 0, only call
swapItemsFirstTwo when items.length > 1, and for option helpers check
items[itemIndex].options.length similarly); keep removeItem and addOption but
validate itemIndex exists when manipulating nested options; return early if the
length checks fail to avoid performing the operation.

---

Nitpick comments:
In `@playgrounds/angular/src/routes/todos/todos.component.ts`:
- Around line 209-225: The handlers handleMoveFirstToEnd, handleSwapFirstTwo,
and handleReplaceFirst currently guard against out-of-bounds indices even though
the field-array helpers move, swap, and replace already no-op for invalid
indices; remove any redundant index-guarding code around these handlers so they
call move/swap/replace directly (as shown) and optionally disable or hide the UI
buttons when fieldArray.items().length is too small to avoid confusing no-op
clicks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 61aa2225-6122-4a6e-b1d2-d3df1f5d57cf

📥 Commits

Reviewing files that changed from the base of the PR and between 975e8e9 and 69baea5.

⛔ Files ignored due to path filters (2)
  • playgrounds/angular/public/fonts/lexend-400.woff2 is excluded by !**/*.woff2
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (82)
  • .gitignore
  • frameworks/angular/CHANGELOG.md
  • frameworks/angular/eslint.config.ts
  • frameworks/angular/package.json
  • frameworks/angular/rolldown.config.ts
  • frameworks/angular/src/components/FormischField/FormischField.test.ts
  • frameworks/angular/src/components/FormischField/FormischField.ts
  • frameworks/angular/src/components/FormischField/index.ts
  • frameworks/angular/src/components/FormischFieldArray/FormischFieldArray.test.ts
  • frameworks/angular/src/components/FormischFieldArray/FormischFieldArray.ts
  • frameworks/angular/src/components/FormischFieldArray/index.ts
  • frameworks/angular/src/components/FormischForm/FormischForm.test.ts
  • frameworks/angular/src/components/FormischForm/FormischForm.ts
  • frameworks/angular/src/components/FormischForm/index.ts
  • frameworks/angular/src/components/index.ts
  • frameworks/angular/src/functions/index.ts
  • frameworks/angular/src/functions/injectField/index.ts
  • frameworks/angular/src/functions/injectField/injectField.test-d.ts
  • frameworks/angular/src/functions/injectField/injectField.test.ts
  • frameworks/angular/src/functions/injectField/injectField.ts
  • frameworks/angular/src/functions/injectFieldArray/index.ts
  • frameworks/angular/src/functions/injectFieldArray/injectFieldArray.test-d.ts
  • frameworks/angular/src/functions/injectFieldArray/injectFieldArray.test.ts
  • frameworks/angular/src/functions/injectFieldArray/injectFieldArray.ts
  • frameworks/angular/src/functions/injectForm/index.ts
  • frameworks/angular/src/functions/injectForm/injectForm.test-d.ts
  • frameworks/angular/src/functions/injectForm/injectForm.test.ts
  • frameworks/angular/src/functions/injectForm/injectForm.ts
  • frameworks/angular/src/index.ts
  • frameworks/angular/src/types/field.ts
  • frameworks/angular/src/types/form.ts
  • frameworks/angular/src/types/index.ts
  • frameworks/angular/src/types/utils.ts
  • frameworks/angular/src/utils/index.ts
  • frameworks/angular/src/utils/readSignalOrValue/index.ts
  • frameworks/angular/src/utils/readSignalOrValue/readSignalOrValue.test.ts
  • frameworks/angular/src/utils/readSignalOrValue/readSignalOrValue.ts
  • frameworks/angular/src/vitest/loadDistComponent.ts
  • frameworks/angular/src/vitest/setup.ts
  • frameworks/angular/tsconfig.build.json
  • frameworks/angular/tsconfig.json
  • frameworks/angular/tsconfig.spec.json
  • frameworks/angular/vitest.config.ts
  • packages/methods/package.json
  • packages/methods/tsdown.config.ts
  • playgrounds/angular/index.html
  • playgrounds/angular/package.json
  • playgrounds/angular/src/app.component.ts
  • playgrounds/angular/src/app.config.ts
  • playgrounds/angular/src/app.routes.ts
  • playgrounds/angular/src/components/action-button.component.ts
  • playgrounds/angular/src/components/auto-animate.directive.ts
  • playgrounds/angular/src/components/button-group.component.ts
  • playgrounds/angular/src/components/checkbox.component.ts
  • playgrounds/angular/src/components/color-button.component.ts
  • playgrounds/angular/src/components/expandable.component.ts
  • playgrounds/angular/src/components/file-input.component.ts
  • playgrounds/angular/src/components/form-error.component.ts
  • playgrounds/angular/src/components/form-footer.component.ts
  • playgrounds/angular/src/components/form-header.component.ts
  • playgrounds/angular/src/components/input-errors.component.ts
  • playgrounds/angular/src/components/input-label.component.ts
  • playgrounds/angular/src/components/radio-group.component.ts
  • playgrounds/angular/src/components/radio.component.ts
  • playgrounds/angular/src/components/select.component.ts
  • playgrounds/angular/src/components/slider.component.ts
  • playgrounds/angular/src/components/spinner.component.ts
  • playgrounds/angular/src/components/text-input.component.ts
  • playgrounds/angular/src/components/unstyled-button.component.ts
  • playgrounds/angular/src/global.css
  • playgrounds/angular/src/icons/angle-down-icon.component.ts
  • playgrounds/angular/src/main.ts
  • playgrounds/angular/src/routes/login/login.component.ts
  • playgrounds/angular/src/routes/nested/nested.component.ts
  • playgrounds/angular/src/routes/payment/payment.component.ts
  • playgrounds/angular/src/routes/special/special.component.ts
  • playgrounds/angular/src/routes/todos/todos.component.ts
  • playgrounds/angular/src/utils/disable-transitions.ts
  • playgrounds/angular/tsconfig.app.json
  • playgrounds/angular/tsconfig.json
  • playgrounds/angular/vite.config.ts
  • prettier.config.js

Comment thread frameworks/angular/CHANGELOG.md
Comment thread playgrounds/angular/package.json Outdated
Comment thread playgrounds/angular/src/app.config.ts
Comment thread playgrounds/angular/src/components/file-input.component.ts Outdated
Comment thread playgrounds/angular/src/components/input-label.component.ts Outdated
Comment thread playgrounds/angular/src/global.css
Comment thread playgrounds/angular/src/routes/nested/nested.component.ts
The branch had set importOrderParserPlugins to ['typescript',
'decorators-legacy'] to parse Angular decorators, which dropped the
default 'jsx' plugin and broke the Prettier check for the .tsx-based
frameworks (preact, qwik, react, solid). Re-add 'jsx' so both JSX and
Angular decorators parse. Also format website/HeadContent.tsx, an
unformatted import inherited from main.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 28916d21f0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frameworks/angular/package.json Outdated
Comment thread frameworks/angular/src/functions/injectField/injectField.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with 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.

Inline comments:
In `@package.json`:
- Line 47: The package.json change tightened the TypeScript semver from "^5.8.3"
to "~5.9.3" which pins installs to 5.9.x; confirm this is intentional for build
stability or revert to a caret range to allow minor/major upgrades. If you want
to allow future minor/major updates, update the "typescript" dependency string
back to "^5.9.3" (or "^5.8.3" if you prefer preserving the previous baseline);
if pinning is intentional, add a short comment in the repo docs or a
package.json comment block explaining why "typescript": "~5.9.3" is required for
reproducible builds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 745a1e4e-202a-4693-8cc2-1da969fd7109

📥 Commits

Reviewing files that changed from the base of the PR and between 3b90462 and 28916d2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • frameworks/angular/package.json
  • frameworks/angular/src/components/FormischField/FormischField.test.ts
  • frameworks/angular/src/components/FormischFieldArray/FormischFieldArray.test.ts
  • frameworks/angular/src/components/FormischForm/FormischForm.test.ts
  • frameworks/angular/src/functions/injectField/injectField.test.ts
  • frameworks/angular/src/functions/injectFieldArray/injectFieldArray.test.ts
  • frameworks/angular/src/functions/injectForm/injectForm.test.ts
  • package.json
  • playgrounds/angular/package.json
  • playgrounds/angular/src/app.config.ts
✅ Files skipped from review due to trivial changes (2)
  • playgrounds/angular/src/app.config.ts
  • playgrounds/angular/package.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • frameworks/angular/src/components/FormischFieldArray/FormischFieldArray.test.ts
  • frameworks/angular/src/functions/injectFieldArray/injectFieldArray.test.ts
  • frameworks/angular/src/functions/injectField/injectField.test.ts
  • frameworks/angular/src/components/FormischForm/FormischForm.test.ts

Comment thread package.json

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 44 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread frameworks/angular/src/directives/FormischForm/FormischForm.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6bd282beb7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frameworks/angular/package.json Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with 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.

Inline comments:
In `@frameworks/angular/src/directives/FormischField/FormischField.ts`:
- Around line 34-38: The JSDoc example for the FormischField directive shows an
incorrect microsyntax (a stray semicolon before "of") that doesn't match actual
usage; update the example in FormischField.ts to use the same syntax as
tests/playground by moving the path and `of form` into the same clause (e.g.,
`*formischField="['todos', i, 'label'] of form; let field"`), ensuring the
directive name FormischField and the example binding match real-world usage.

In `@frameworks/angular/src/directives/FormischFieldArray/FormischFieldArray.ts`:
- Around line 34-38: The docs example for the FormischFieldArray microsyntax is
incorrect: replace the current example string "*formischFieldArray=\"['todos'];
of form; let fieldArray\"" with the correct microsyntax used in the playground,
e.g. "*formischFieldArray=\"['todos'] of form; let fieldArray\"" so the `of`
sits after the bracketed path (reference FormischFieldArray in the directive
docs).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 143de9f9-2102-4832-9c05-77f100492487

📥 Commits

Reviewing files that changed from the base of the PR and between 28916d2 and 6bd282b.

📒 Files selected for processing (38)
  • frameworks/angular/package.json
  • frameworks/angular/src/directives/FormischControl/FormischControl.test.ts
  • frameworks/angular/src/directives/FormischControl/FormischControl.ts
  • frameworks/angular/src/directives/FormischControl/index.ts
  • frameworks/angular/src/directives/FormischField/FormischField.test-d.ts
  • frameworks/angular/src/directives/FormischField/FormischField.test.ts
  • frameworks/angular/src/directives/FormischField/FormischField.ts
  • frameworks/angular/src/directives/FormischField/index.ts
  • frameworks/angular/src/directives/FormischFieldArray/FormischFieldArray.test-d.ts
  • frameworks/angular/src/directives/FormischFieldArray/FormischFieldArray.test.ts
  • frameworks/angular/src/directives/FormischFieldArray/FormischFieldArray.ts
  • frameworks/angular/src/directives/FormischFieldArray/index.ts
  • frameworks/angular/src/directives/FormischForm/FormischForm.test.ts
  • frameworks/angular/src/directives/FormischForm/FormischForm.ts
  • frameworks/angular/src/directives/FormischForm/index.ts
  • frameworks/angular/src/directives/index.ts
  • frameworks/angular/src/functions/injectField/injectField.test-d.ts
  • frameworks/angular/src/functions/injectField/injectField.test.ts
  • frameworks/angular/src/functions/injectField/injectField.ts
  • frameworks/angular/src/index.ts
  • frameworks/angular/src/types/control.ts
  • frameworks/angular/src/types/field.ts
  • playgrounds/angular/src/app.config.ts
  • playgrounds/angular/src/components/checkbox.component.ts
  • playgrounds/angular/src/components/file-input.component.ts
  • playgrounds/angular/src/components/form-footer.component.ts
  • playgrounds/angular/src/components/form-header.component.ts
  • playgrounds/angular/src/components/input-label.component.ts
  • playgrounds/angular/src/components/radio-group.component.ts
  • playgrounds/angular/src/components/radio.component.ts
  • playgrounds/angular/src/components/select.component.ts
  • playgrounds/angular/src/components/slider.component.ts
  • playgrounds/angular/src/components/text-input.component.ts
  • playgrounds/angular/src/routes/login/login.component.ts
  • playgrounds/angular/src/routes/nested/nested.component.ts
  • playgrounds/angular/src/routes/payment/payment.component.ts
  • playgrounds/angular/src/routes/special/special.component.ts
  • playgrounds/angular/src/routes/todos/todos.component.ts
💤 Files with no reviewable changes (3)
  • frameworks/angular/src/directives/FormischFieldArray/index.ts
  • frameworks/angular/src/directives/FormischForm/index.ts
  • frameworks/angular/src/directives/FormischField/index.ts
✅ Files skipped from review due to trivial changes (1)
  • frameworks/angular/src/directives/FormischControl/index.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • playgrounds/angular/src/app.config.ts
  • playgrounds/angular/src/components/form-footer.component.ts
  • playgrounds/angular/src/routes/login/login.component.ts
  • playgrounds/angular/src/components/input-label.component.ts
  • playgrounds/angular/src/routes/todos/todos.component.ts
  • frameworks/angular/src/functions/injectField/injectField.test.ts
  • playgrounds/angular/src/routes/special/special.component.ts
  • playgrounds/angular/src/routes/nested/nested.component.ts
  • frameworks/angular/package.json

Comment thread frameworks/angular/src/directives/FormischField/FormischField.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 8 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="frameworks/angular/src/directives/FormischForm/FormischForm.ts">

<violation number="1" location="frameworks/angular/src/directives/FormischForm/FormischForm.ts:43">
P2: Using a callback input for submit can break common Angular class-method handlers because `[formischSubmit]="onSubmit"` passes an unbound function. Invoking it later can fail when `onSubmit` uses `this`.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

/**
* The submit handler called when validation succeeds.
*/
readonly formischSubmit: InputSignal<SubmitEventHandler<TSchema>> =

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Using a callback input for submit can break common Angular class-method handlers because [formischSubmit]="onSubmit" passes an unbound function. Invoking it later can fail when onSubmit uses this.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frameworks/angular/src/directives/FormischForm/FormischForm.ts, line 43:

<comment>Using a callback input for submit can break common Angular class-method handlers because `[formischSubmit]="onSubmit"` passes an unbound function. Invoking it later can fail when `onSubmit` uses `this`.</comment>

<file context>
@@ -38,27 +38,27 @@ export class FormischForm<TSchema extends FormSchema = FormSchema> {
    */
-  readonly formischSubmit: OutputEmitterRef<v.InferOutput<TSchema>> =
-    output<v.InferOutput<TSchema>>();
+  readonly formischSubmit: InputSignal<SubmitEventHandler<TSchema>> =
+    input.required<SubmitEventHandler<TSchema>>();
 
</file context>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c03b388b52

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

protected handleFormSubmit(event: SubmitEvent): void {
void handleSubmit(this.formischForm(), this.formischSubmit())(event);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve component context for submit callbacks

When consumers pass a normal Angular component method here, e.g. [formischSubmit]="submit" where submit() reads this, this retrieves the bare function input and handleSubmit later invokes it as handler(...), so the component instance is not the receiver and this is undefined. The playground uses arrow fields, but class methods are the common Angular submit-handler shape; consider using an output/template statement API or otherwise documenting/enforcing a bound callback.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 403bf01518

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

},
"peerDependencies": {
"@angular/common": ">=17.0.0",
"@angular/core": ">=17.3.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Align peer range with the Angular compiler version

Because this library is compiled in partial mode with @angular/compiler-cli 21, Angular applications need an Angular compiler/linker that is at least as new as the compiler that produced the library. With this peer range, Angular 17.3 through 20 projects can install @formisch/angular successfully but then fail when linking/compiling the published partial-Ivy output. Either build the package with the oldest Angular version you intend to support or raise the Angular peer range to the build major.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 89 out of 92 changed files in this pull request and generated 4 comments.

Comment thread playgrounds/angular/src/utils/disable-transitions.ts
Comment thread playgrounds/angular/src/app.component.ts
Comment thread playgrounds/angular/src/components/checkbox.component.ts
Comment thread prettier.config.js
…ecycle fixes (#130)

* Use isSignal() instead of typeof check in readSignalOrValue

* Test validate initial triggers validation after first render

Add a test that renders a real component, waits for stability to flush
the afterNextRender callback, then gives the microtask queue one turn so
the async validateFormInput promise resolves before asserting that
isValid() is false.

* Fix subscription leak, setTimeout, and location.pathname in AppComponent

* Replace FieldStore<any, any> with FieldStore in playground components

Seven reusable input components (TextInput, Select, Checkbox, Radio, RadioGroup, Slider, FileInput) were typed with FieldStore<any, any>, defeating the type safety that ngTemplateContextGuard on the structural directives provides. Replace with FieldStore which relies on the default generic parameters FieldStore<FormSchema, RequiredPath>, preserving the full type contract without any.

* Upgrade to Angular 22 and fix Angular 22 compatibility issues

Bump all @angular/* packages from ^21.0.0 to ^22.0.0 in the framework
and playground package.json files. Angular 22 requires TypeScript 6.0.x,
so TypeScript is bumped from ~5.9.3 to ~6.0.3 in both packages.

Angular 22 changed several behaviors in zoneless mode that required fixes:

Event handler event.currentTarget is null when handler executes.
Angular 22's zoneless scheduler defers host binding event handlers via
microtasks. By the time the deferred handler runs, event.currentTarget has
been reset to null by the native event propagation. Change FieldControl.onInput
from (event: Event) => void to (element: FieldElement) => void so it receives
the stable element reference instead. FormischControl now calls the internal
handleInput() method which passes this.elementRef.nativeElement directly.

Form submission async chain is not tracked by whenStable().
The fire-and-forget void handleSubmit(...) pattern means Angular's scheduler
has no visibility into when the async chain completes. Inject PendingTasks into
FormischForm and register the submit chain as a pending task so whenStable()
correctly waits for validation, the submit handler, and cleanup to finish.

Computed signals read outside reactive contexts return stale values.
Angular 22 stops tracking computed dependencies when they are read outside
of a template or effect context. After an async signal update (Promise
callback), a computed last read in a non-reactive context does not see the
new value. The isSubmitting test reads the raw signal value via [INTERNAL]
for the final assertion to work around this.

* Use event.target instead of elementRef in FormischControl onInput

Replace the handleInput() indirection with the Angular-native pattern:
pass $event directly to control().onInput() and use event.target inside
the implementation instead of event.currentTarget.

event.target is the element that dispatched the event and stays valid
after propagation ends. event.currentTarget is reset to null once the
synchronous propagation finishes, which can cause issues if Angular's
scheduler defers the handler. Angular's own DefaultValueAccessor and
CheckboxControlValueAccessor use event.target for the same reason.

This removes the handleInput() method, restores the host binding to
control().onInput($event), and reverts FieldControl.onInput back to
(event: Event) => void — consistent with how other framework adapters
pass events to their input handlers.

* Move INTERNAL import to top of FormischForm test

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 94291b61b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

},
"peerDependencies": {
"@angular/common": ">=17.0.0",
"@angular/core": ">=17.3.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Raise the Angular core peer for PendingTasks

Fresh evidence: the current FormischForm imports PendingTasks from @angular/core, and Angular's API docs mark PendingTasks as stable since v20.0. With the advertised @angular/core >=17.3.0 peer range, Angular 17.3–19 apps can install this package but fail to compile/bundle because their core package does not export PendingTasks; raise the peer range to a version that provides every imported Angular API or avoid this API for older peers.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add @formisch/angular package with playground

3 participants