Skip to content

Conversation

@Elm1992
Copy link
Contributor

@Elm1992 Elm1992 commented Nov 8, 2025

Description

增加 form 组件展开收起的事件,我的需求是收起的时候要清空所有收起项,应该还有些别的需求吧。

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update
  • Please, don't make changes to pnpm-lock.yaml unless you introduce a new test example.

Checklist

ℹ️ Check all checkboxes - this will indicate that you have done everything in accordance with the rules in CONTRIBUTING.

  • If you introduce new functionality, document it. You can run documentation with pnpm run docs:dev command.
  • Run the tests with pnpm test.
  • Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with feat:, fix:, perf:, docs:, or chore:.
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Summary by CodeRabbit

  • New Features

    • Added an optional callback to receive form collapse/expand state changes so apps can react when forms are toggled.
  • Behavior Changes

    • Form API input is now optional, enabling use of the form component without providing an external form API and improving robustness when omitted.

@changeset-bot
Copy link

changeset-bot bot commented Nov 8, 2025

⚠️ No Changeset found

Latest commit: 665a71f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 8, 2025

Walkthrough

Added an optional handleCollapsedChange callback to the Vben Form API and wired it through types, default state, and component handlers; also made formApi optional and added defensive nullish checks in form usage components. (50 words)

Changes

Cohort / File(s) Summary
Types
packages/@core/ui-kit/form-ui/src/types.ts
Added optional prop handleCollapsedChange?: (collapsed: boolean) => void to VbenFormProps.
Form API
packages/@core/ui-kit/form-ui/src/form-api.ts
Initialized handleCollapsedChange in default Vben form props (default undefined).
Context Types
packages/@core/ui-kit/form-ui/src/use-form-context.ts
Made formApi optional on ExtendFormProps (formApi?: ExtendedFormApi).
Component Implementations
packages/@core/ui-kit/form-ui/src/vben-form.vue, packages/@core/ui-kit/form-ui/src/vben-use-form.vue
Updated handleUpdateCollapsed to assign collapsed boolean directly and call handleCollapsedChange (optional chaining). Added nullish/optional chaining guards around many formApi accesses and state usages.
Documentation
docs/src/components/common-ui/vben-form.md
Documented new handleCollapsedChange prop in API and props list.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as User UI (vben-form)
  participant Comp as vben-use-form / vben-form component
  participant Consumer as Consumer (parent)

  note right of Comp `#e6f7ff`: Collapse toggle triggered
  UI ->> Comp: toggleCollapsed(value: boolean)
  alt collapsed value changed
    Comp ->> Comp: update internal state.collapsed = value
    Comp ->> Consumer: call handleCollapsedChange?(value)
    note right of Consumer `#f0fff0`: optional callback invoked
  else no change
    note right of Comp `#fff7e6`: no callback
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Changes span types, default state, docs, and multiple component files with defensive-chaining updates.
  • Areas needing extra attention:
    • packages/@core/ui-kit/form-ui/src/vben-use-form.vue — many optional chaining changes and async guards.
    • Interaction between optional formApi and existing lifecycle/watch flows.
    • Correctness of handleUpdateCollapsed calls and any consumers expecting previous behavior.

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • anncwb
  • vince292007
  • mynetfan
  • jinmao88

Poem

🐇 A little hop, a gentle change,
When panels fold or wide arrange,
I call, I tell, the state is true,
A rabbit's note — from old to new. ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add form handleCollapsedChange event' is clear and directly summarizes the main change - adding a new callback event to the form component for handling collapsed/expanded state changes.
Description check ✅ Passed The PR description identifies the feature type (new feature) and includes documentation and checklist sections, but the description is minimal and mostly in Chinese, lacking English detail about the implementation and requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0139d41 and 665a71f.

📒 Files selected for processing (2)
  • packages/@core/ui-kit/form-ui/src/vben-form.vue (1 hunks)
  • packages/@core/ui-kit/form-ui/src/vben-use-form.vue (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/@core/ui-kit/form-ui/src/vben-form.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Check (ubuntu-latest)
  • GitHub Check: Check (windows-latest)
  • GitHub Check: Lint (windows-latest)
  • GitHub Check: Lint (ubuntu-latest)
  • GitHub Check: Test (windows-latest)
  • GitHub Check: post-update (windows-latest)
  • GitHub Check: post-update (ubuntu-latest)
🔇 Additional comments (3)
packages/@core/ui-kit/form-ui/src/vben-use-form.vue (3)

28-28: LGTM! Making formApi optional aligns with the broader PR changes.

The change to make formApi optional is consistent with related modifications in other files (per the AI summary, use-form-context.ts also relaxes this requirement). The component handles this appropriately with optional chaining throughout.


46-50: LGTM! The callback implementation correctly implements the new feature.

The handleUpdateCollapsed function properly:

  1. Updates the form state with the new collapsed value
  2. Invokes the new handleCollapsedChange callback to notify subscribers

The callback is safely guarded with optional chaining and is called after the state update, ensuring consistent behavior.


53-53: Defensive null checks are appropriate given optional formApi.

The optional chaining throughout the file (lines 53, 63, 67, 79, 97, 114, 131) is consistent and appropriate now that formApi is optional. Line 97's nullish coalescing (?? {}) provides a safe fallback when form values cannot be retrieved.

However, consider whether the component should provide user feedback when formApi is not available but operations like validation or submission are attempted. Currently, these operations will silently fail without error messages.

Also applies to: 63-63, 67-67, 79-79, 97-97, 114-114, 131-131


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/@core/ui-kit/form-ui/src/vben-use-form.vue (1)

46-51: Consider simplifying boolean coercion.

The !!value coercion is defensive but unnecessary since value is already typed as boolean. You could simplify to const collapsedValue = value; or use value directly. However, the defensive coding provides runtime safety if the type contract is violated.

Apply this diff if you prefer a cleaner approach:

 const handleUpdateCollapsed = (value: boolean) => {
-  const collapsedValue = !!value;
-  props.formApi?.setState({ collapsed: collapsedValue });
+  props.formApi?.setState({ collapsed: value });
   // 触发收起展开状态变化回调
-  forward.value.handleCollapsedChange?.(collapsedValue);
+  forward.value.handleCollapsedChange?.(value);
 };
packages/@core/ui-kit/form-ui/src/vben-form.vue (1)

42-47: Consider simplifying boolean coercion (same pattern as vben-use-form.vue).

Similar to the implementation in vben-use-form.vue, the !!value coercion is unnecessary given the typed parameter. The defensive coding is acceptable but could be simplified for clarity.

Apply this diff for a cleaner approach:

 const handleUpdateCollapsed = (value: boolean) => {
-  const collapsedValue = !!value;
-  currentCollapsed.value = collapsedValue;
+  currentCollapsed.value = value;
   // 触发收起展开状态变化回调
-  props.handleCollapsedChange?.(collapsedValue);
+  props.handleCollapsedChange?.(value);
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e09fa4 and 0139d41.

📒 Files selected for processing (6)
  • docs/src/components/common-ui/vben-form.md (1 hunks)
  • packages/@core/ui-kit/form-ui/src/form-api.ts (1 hunks)
  • packages/@core/ui-kit/form-ui/src/types.ts (1 hunks)
  • packages/@core/ui-kit/form-ui/src/use-form-context.ts (1 hunks)
  • packages/@core/ui-kit/form-ui/src/vben-form.vue (1 hunks)
  • packages/@core/ui-kit/form-ui/src/vben-use-form.vue (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/@core/ui-kit/form-ui/src/use-form-context.ts (1)
packages/@core/ui-kit/form-ui/src/types.ts (2)
  • VbenFormProps (350-434)
  • ExtendedFormApi (436-440)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Lint (ubuntu-latest)
  • GitHub Check: Lint (windows-latest)
  • GitHub Check: Check (windows-latest)
  • GitHub Check: Check (ubuntu-latest)
  • GitHub Check: Test (windows-latest)
  • GitHub Check: post-update (ubuntu-latest)
  • GitHub Check: post-update (windows-latest)
🔇 Additional comments (3)
packages/@core/ui-kit/form-ui/src/types.ts (1)

382-385: LGTM! Type definition is correct.

The optional callback property is properly typed with a clear signature. The documentation comment clearly describes its purpose.

packages/@core/ui-kit/form-ui/src/form-api.ts (1)

39-39: LGTM! Default state initialization is correct.

The initialization follows the established pattern for other callback handlers in the default state.

docs/src/components/common-ui/vben-form.md (1)

338-338: LGTM! Documentation is complete and accurate.

The prop is properly documented with correct type signature and clear description.

import { getDefaultsForSchema } from 'zod-defaults';

type ExtendFormProps = VbenFormProps & { formApi: ExtendedFormApi };
type ExtendFormProps = VbenFormProps & { formApi?: ExtendedFormApi };
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify that all consumers handle optional formApi.

Making formApi optional in ExtendFormProps could impact consumers that inject form props via injectFormProps. Ensure all usages safely handle the case where formApi is undefined.

Run the following script to verify all formApi usages properly handle the optional case:


🏁 Script executed:

#!/bin/bash
# Description: Find all usages of injectFormProps and verify optional chaining is used for formApi access

# Find all usages of injectFormProps
echo "=== Finding injectFormProps usages ==="
rg -n "injectFormProps" --type=ts --type=vue -A 5

# Find direct formApi property accesses that might not use optional chaining
echo -e "\n=== Finding potentially unsafe formApi accesses ==="
rg -n "formApi\.[a-zA-Z]" --type=ts --type=vue -C 2 | rg -v "formApi\?\."

Length of output: 147


🏁 Script executed:

#!/bin/bash
# Description: Find injectFormProps usages and formApi accesses without vue type constraints

# First, look at the file in question
echo "=== Viewing use-form-context.ts ==="
find . -name "use-form-context.ts" -type f | head -5 | xargs cat 2>/dev/null || echo "File not found"

echo -e "\n=== Finding injectFormProps usages (without type filter) ==="
rg -n "injectFormProps" -A 5 2>/dev/null | head -100

echo -e "\n=== Finding formApi direct accesses (without optional chaining) ==="
rg -n "\.formApi\." -C 2 2>/dev/null | head -100

echo -e "\n=== Finding formApi accesses with optional chaining ==="
rg -n "\.formApi\?" -C 2 2>/dev/null | head -50

echo -e "\n=== Finding all formApi references in context ==="
rg -n "formApi" --max-count=50 2>/dev/null

Length of output: 27507


Fix unsafe formApi accesses in vben-use-form.vue that don't account for optional value.

Making formApi optional in ExtendFormProps introduces a type mismatch with consumers. While form-actions.vue safely guards with if (!props.formApi) before access, vben-use-form.vue directly accesses formApi without protection:

  • Line 64: forward.value.formApi.validateAndSubmitForm()
  • Line 98: cloneDeep(await forward.value.formApi.getValues())

Additionally, the Props type declaration in vben-use-form.vue (line 28) declares formApi: ExtendedFormApi as required, which conflicts with the now-optional injection contract. Update the Props declaration to formApi?: ExtendedFormApi and protect these two accesses with optional chaining or guard conditions.

🤖 Prompt for AI Agents
In packages/@core/ui-kit/form-ui/src/use-form-context.ts line 16 and
packages/@core/ui-kit/form-ui/src/components/vben-use-form.vue lines 28, 64, 98,
update types and guard unsafe accesses: change the vben-use-form.vue Props
declaration from formApi: ExtendedFormApi to formApi?: ExtendedFormApi to match
ExtendFormProps, and protect usages at lines 64 and 98 by checking for presence
(if (forward.value.formApi) ...) or using optional chaining
(forward.value.formApi?.validateAndSubmitForm(), cloneDeep(await
forward.value.formApi?.getValues() ?? {})) so no code assumes formApi is
non-null. Ensure any downstream typing uses the optional type.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant