Add @formisch/angular package with playground#124
Conversation
- 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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis pull request introduces a complete Angular integration for Formisch, including a new |
There was a problem hiding this comment.
💡 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".
There was a problem hiding this comment.
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/angularpackage withinjectForm/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/methodsto ship an./angularentry 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.
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (1)
playgrounds/angular/src/routes/todos/todos.component.ts (1)
209-225: ⚡ Quick winField-array helpers already no-op on out-of-bounds indices; guards aren’t necessary
move,swap, andreplaceeach check that the provided indices fall within0..items.length-1(andmove/swapalso require indices to differ). Whentodosis empty or too short, the helpers skip the mutation entirely, so the handlers won’t hit invalidchildren[...]accesses. Optional: disable/hide the “Move first to end” / “Swap first two” / “Replace first” buttons whenfieldArray.items().lengthis 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
⛔ Files ignored due to path filters (2)
playgrounds/angular/public/fonts/lexend-400.woff2is excluded by!**/*.woff2pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (82)
.gitignoreframeworks/angular/CHANGELOG.mdframeworks/angular/eslint.config.tsframeworks/angular/package.jsonframeworks/angular/rolldown.config.tsframeworks/angular/src/components/FormischField/FormischField.test.tsframeworks/angular/src/components/FormischField/FormischField.tsframeworks/angular/src/components/FormischField/index.tsframeworks/angular/src/components/FormischFieldArray/FormischFieldArray.test.tsframeworks/angular/src/components/FormischFieldArray/FormischFieldArray.tsframeworks/angular/src/components/FormischFieldArray/index.tsframeworks/angular/src/components/FormischForm/FormischForm.test.tsframeworks/angular/src/components/FormischForm/FormischForm.tsframeworks/angular/src/components/FormischForm/index.tsframeworks/angular/src/components/index.tsframeworks/angular/src/functions/index.tsframeworks/angular/src/functions/injectField/index.tsframeworks/angular/src/functions/injectField/injectField.test-d.tsframeworks/angular/src/functions/injectField/injectField.test.tsframeworks/angular/src/functions/injectField/injectField.tsframeworks/angular/src/functions/injectFieldArray/index.tsframeworks/angular/src/functions/injectFieldArray/injectFieldArray.test-d.tsframeworks/angular/src/functions/injectFieldArray/injectFieldArray.test.tsframeworks/angular/src/functions/injectFieldArray/injectFieldArray.tsframeworks/angular/src/functions/injectForm/index.tsframeworks/angular/src/functions/injectForm/injectForm.test-d.tsframeworks/angular/src/functions/injectForm/injectForm.test.tsframeworks/angular/src/functions/injectForm/injectForm.tsframeworks/angular/src/index.tsframeworks/angular/src/types/field.tsframeworks/angular/src/types/form.tsframeworks/angular/src/types/index.tsframeworks/angular/src/types/utils.tsframeworks/angular/src/utils/index.tsframeworks/angular/src/utils/readSignalOrValue/index.tsframeworks/angular/src/utils/readSignalOrValue/readSignalOrValue.test.tsframeworks/angular/src/utils/readSignalOrValue/readSignalOrValue.tsframeworks/angular/src/vitest/loadDistComponent.tsframeworks/angular/src/vitest/setup.tsframeworks/angular/tsconfig.build.jsonframeworks/angular/tsconfig.jsonframeworks/angular/tsconfig.spec.jsonframeworks/angular/vitest.config.tspackages/methods/package.jsonpackages/methods/tsdown.config.tsplaygrounds/angular/index.htmlplaygrounds/angular/package.jsonplaygrounds/angular/src/app.component.tsplaygrounds/angular/src/app.config.tsplaygrounds/angular/src/app.routes.tsplaygrounds/angular/src/components/action-button.component.tsplaygrounds/angular/src/components/auto-animate.directive.tsplaygrounds/angular/src/components/button-group.component.tsplaygrounds/angular/src/components/checkbox.component.tsplaygrounds/angular/src/components/color-button.component.tsplaygrounds/angular/src/components/expandable.component.tsplaygrounds/angular/src/components/file-input.component.tsplaygrounds/angular/src/components/form-error.component.tsplaygrounds/angular/src/components/form-footer.component.tsplaygrounds/angular/src/components/form-header.component.tsplaygrounds/angular/src/components/input-errors.component.tsplaygrounds/angular/src/components/input-label.component.tsplaygrounds/angular/src/components/radio-group.component.tsplaygrounds/angular/src/components/radio.component.tsplaygrounds/angular/src/components/select.component.tsplaygrounds/angular/src/components/slider.component.tsplaygrounds/angular/src/components/spinner.component.tsplaygrounds/angular/src/components/text-input.component.tsplaygrounds/angular/src/components/unstyled-button.component.tsplaygrounds/angular/src/global.cssplaygrounds/angular/src/icons/angle-down-icon.component.tsplaygrounds/angular/src/main.tsplaygrounds/angular/src/routes/login/login.component.tsplaygrounds/angular/src/routes/nested/nested.component.tsplaygrounds/angular/src/routes/payment/payment.component.tsplaygrounds/angular/src/routes/special/special.component.tsplaygrounds/angular/src/routes/todos/todos.component.tsplaygrounds/angular/src/utils/disable-transitions.tsplaygrounds/angular/tsconfig.app.jsonplaygrounds/angular/tsconfig.jsonplaygrounds/angular/vite.config.tsprettier.config.js
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>
There was a problem hiding this comment.
💡 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".
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (10)
frameworks/angular/package.jsonframeworks/angular/src/components/FormischField/FormischField.test.tsframeworks/angular/src/components/FormischFieldArray/FormischFieldArray.test.tsframeworks/angular/src/components/FormischForm/FormischForm.test.tsframeworks/angular/src/functions/injectField/injectField.test.tsframeworks/angular/src/functions/injectFieldArray/injectFieldArray.test.tsframeworks/angular/src/functions/injectForm/injectForm.test.tspackage.jsonplaygrounds/angular/package.jsonplaygrounds/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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
💡 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".
There was a problem hiding this comment.
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
📒 Files selected for processing (38)
frameworks/angular/package.jsonframeworks/angular/src/directives/FormischControl/FormischControl.test.tsframeworks/angular/src/directives/FormischControl/FormischControl.tsframeworks/angular/src/directives/FormischControl/index.tsframeworks/angular/src/directives/FormischField/FormischField.test-d.tsframeworks/angular/src/directives/FormischField/FormischField.test.tsframeworks/angular/src/directives/FormischField/FormischField.tsframeworks/angular/src/directives/FormischField/index.tsframeworks/angular/src/directives/FormischFieldArray/FormischFieldArray.test-d.tsframeworks/angular/src/directives/FormischFieldArray/FormischFieldArray.test.tsframeworks/angular/src/directives/FormischFieldArray/FormischFieldArray.tsframeworks/angular/src/directives/FormischFieldArray/index.tsframeworks/angular/src/directives/FormischForm/FormischForm.test.tsframeworks/angular/src/directives/FormischForm/FormischForm.tsframeworks/angular/src/directives/FormischForm/index.tsframeworks/angular/src/directives/index.tsframeworks/angular/src/functions/injectField/injectField.test-d.tsframeworks/angular/src/functions/injectField/injectField.test.tsframeworks/angular/src/functions/injectField/injectField.tsframeworks/angular/src/index.tsframeworks/angular/src/types/control.tsframeworks/angular/src/types/field.tsplaygrounds/angular/src/app.config.tsplaygrounds/angular/src/components/checkbox.component.tsplaygrounds/angular/src/components/file-input.component.tsplaygrounds/angular/src/components/form-footer.component.tsplaygrounds/angular/src/components/form-header.component.tsplaygrounds/angular/src/components/input-label.component.tsplaygrounds/angular/src/components/radio-group.component.tsplaygrounds/angular/src/components/radio.component.tsplaygrounds/angular/src/components/select.component.tsplaygrounds/angular/src/components/slider.component.tsplaygrounds/angular/src/components/text-input.component.tsplaygrounds/angular/src/routes/login/login.component.tsplaygrounds/angular/src/routes/nested/nested.component.tsplaygrounds/angular/src/routes/payment/payment.component.tsplaygrounds/angular/src/routes/special/special.component.tsplaygrounds/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
There was a problem hiding this comment.
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>> = |
There was a problem hiding this comment.
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>
There was a problem hiding this comment.
💡 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); |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
💡 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", |
There was a problem hiding this comment.
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 👍 / 👎.
…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
There was a problem hiding this comment.
💡 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", |
There was a problem hiding this comment.
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 👍 / 👎.
Implements the full Angular framework package for Formisch (
@formisch/angular): types,injectForm/injectField/injectFieldArray, theFormischForm/FormischField/FormischFieldArraycomponents, and a playground with full parity to the other framework playgrounds.Highlights
injectForm,injectField, andinjectFieldArrayexpose reactive Angular signals; the components are thin wrappers that delegate to them.ngc(partial Ivy) compiles the components, then rolldown bundles@formisch/coreand@formisch/methodsintodist(no@formisch/*runtime deps, matching the other frameworks), keeping@angular/*andvalibotas peer dependencies.strictTemplatesenabled for type-safe field paths.Closes #111.
🤖 Generated with Claude Code
Summary by cubic
Adds the Angular package
@formisch/angularwith 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-containedngc+ rolldown build.New Features
injectForm,injectField,injectFieldArrayreturn Angular signals; types:FormStore,FieldStore,FieldArrayStore.FormischForm(disables native validation, registers form, emitsformischSubmit, integrateshandleSubmit, focuses first invalid),FormischField/FormischFieldArray(structural, typed viaof),FormischControl(binds inputs/changes/focus/blur, registers element). AOT- and zoneless-safe.ngc(partial Ivy) then bundle via rolldown; inline@formisch/core/@formisch/methodsvia./angularentries; keep@angular/*andvalibotas peers.AutoAnimateDirective; improved semantics and animations.Dependencies
@formisch/methods: add./angularexport and build target; add optional peer@angular/core.typescript~6.0.3(root stays~5.9.3);valibotto^1.4.1.frameworks/angular.decorators-legacyand restorejsxparser plugin.Written for commit 94291b6. Summary will update on new commits.