fix: trigger onChange when manually clearing input via select all + delete
Title
fix: trigger onChange when manually clearing input via select all + delete
Description
This PR fixes the issue where manually clearing a date input by selecting all text (Ctrl+A/Cmd+A) and pressing Delete/Backspace does not trigger the onChange callback.
Problem
When users manually select and delete date text in the input field:
- ❌
onChangewas NOT triggered - ❌ After blur, the previous date value reappeared
- ❌ Inconsistent with the clear button (×) behavior
This was a UX and accessibility issue that prevented keyboard-only users from clearing dates effectively.
Solution
Changes Made:
-
useInputProps.ts- Added logic to detect empty input and triggeronChange(null) -
Input.tsx- Added handlers for both formatted and non-formatted inputs -
SingleSelector/index.tsx- Updated to properly handle null values -
manual-clear.spec.tsx- Added 11 comprehensive tests
Behavior After Fix:
- ✅ Select all text (Ctrl+A/Cmd+A) and press Delete → input clears immediately
- ✅
onChangeis called with(null, null) - ✅ Matches clear button behavior exactly
- ✅ Works for both Picker and RangePicker
- ✅ Works for all picker modes (date, week, month, year, quarter, time)
Testing
All Tests Pass
- 453 existing tests pass ✅ (no breaking changes)
- 11 new tests added ✅ (comprehensive coverage)
- Total: 16 test suites, 455 tests
Manual Testing
- Click in the input
- Select all text: Ctrl+A (Windows/Linux) or Cmd+A (Mac)
- Press Delete or Backspace
- Verify input clears and
onChangeis triggered
Backward Compatibility
✅ Fully backward compatible - all existing tests pass
- Invalid partial inputs still reset on blur (existing behavior preserved)
- Clear button behavior unchanged
- No API changes
Fixes
Fixes ant-design/ant-design#52473
Summary by CodeRabbit
-
Bug Fixes
- 改进了日期/区间选择器的手动清除与空输入处理:在输入清空或通过清除控件时会显式走清除路径、重置输入并同步外部状态;单选场景在为空且允许清除时会触发清除回调;公共 API 保持不变。
-
Tests
- 新增全面手动清除测试,覆盖通过输入/失焦与清除控件、allowClear 不同配置、无效部分输入、不同行为模式与掩码、范围起止清空等场景,提升一致性验证。
@alii13 is attempting to deploy a commit to the React Component Team on Vercel.
A member of the Team first needs to authorize it.
Summary of Changes
Hello @alii13, I'm Gemini Code Assist[^1]! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request resolves a significant user experience and accessibility flaw in date input components. Previously, manually clearing a date field by selecting all text and pressing delete or backspace would not correctly trigger the onChange event, leading to inconsistent state and the reappearance of old values. The implemented solution ensures that such manual clearing actions are properly recognized, triggering onChange(null) and providing a consistent, accessible experience across all picker types and modes, mirroring the behavior of the dedicated clear button.
Highlights
-
Manual Clear Fix: Implemented a fix to ensure the
onChangecallback is triggered when a date input is manually cleared using "select all + delete/backspace". - Consistent Behavior: The manual clearing behavior now aligns with the dedicated clear button, preventing previous date values from reappearing on blur.
- Enhanced Accessibility: This change improves keyboard accessibility for users who clear date inputs without relying on a mouse.
- Broad Coverage: The fix applies consistently to both single and range pickers, and across all picker modes (date, week, month, year, quarter, time).
- Comprehensive Testing: 11 new, comprehensive tests have been added to validate the new functionality across various scenarios, ensuring robustness.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in pull request comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with :thumbsup: and :thumbsdown: on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
[^1]: Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.
[!NOTE]
Other AI code review bot(s) detected
CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.
Walkthrough
在输入与选择处理路径中加入对手动清空的显式处理:当输入变为空或通过键盘(全选 + Backspace/Delete)清除时,触发相应的清空回调(onChange(null)/onClear),更新输入状态并提前返回以阻止后续处理。
Changes
| Cohort / File(s) | 变更摘要 |
|---|---|
输入组件改动 src/PickerInput/Selector/Input.tsx |
提取顶部输入文本变量并在通用/无格式化路径中检测并处理手动清空:当输入变为空且当前值非空且存在清空图标时,调用 onChange('') 并重置输入值,阻止默认事件并提前返回;同时统一使用顶部提取的 text 变量以避免重复声明。 |
单选选择器 src/PickerInput/Selector/SingleSelector/index.tsx |
将单选变更处理改为接受 `DateType |
输入属性钩子 src/PickerInput/Selector/hooks/useInputProps.ts |
增加空字符串分支:当 text === '' 时先调用 onInvalid(false, index) 与 onChange(null, index) 并提前返回,确保外部状态与无效标记同步并阻止后续验证流程。 |
测试 tests/manual-clear.spec.tsx |
新增手动清空相关测试,覆盖键盘/输入/blur 清空、allowClear 开关、range picker 两端清空、不同模式与掩码下行为,使用 dayjs generateConfig、en_US locale 与假定定时器模拟异步验证。 |
Sequence Diagram(s)
sequenceDiagram
participant 用户
participant Input as Input 组件
participant Hook as useInputProps
participant Selector as SingleSelector
participant Parent as 上层 onChange/onClear
Note over 用户,Input: 用户全选并按 Delete/Backspace 或 将输入清空
用户->>Input: 输入事件 / keydown
alt 检测到手动清空 (text === '' 且 当前值非空)
Input->>Input: 阻止默认、重置输入值
Input->>Parent: onChange(null) / onClear()
Note right of Parent: 上层接收空值清空事件
else 常规格式化/校验流程
Input->>Hook: 继续格式化与校验(可能触发 onModify/onChange)
end
Note over Input,Hook: 若 text === '' 导致钩子提前返回
Input->>Hook: text === ''
Hook->>Hook: onInvalid(false), onChange(null) 并提前返回
Hook-->>Parent: onChange(null)
Note over Selector: 通过选择器接口触发选择/清空
用户->>Selector: 选择器产生 date (可能为 null)
alt date === null
Selector->>Parent: onClear()
else
Selector->>Parent: onChange([date])
end
Estimated code review effort
🎯 3 (中等) | ⏱️ ~20-25 minutes
需要额外关注:
-
src/PickerInput/Selector/Input.tsx中对选区/光标状态与 preventDefault 的判断是否覆盖所有输入场景(含掩码/格式化路径)。 -
src/PickerInput/Selector/hooks/useInputProps.ts的空字符串早退对去抖、异步验证和现有校验流程的影响。 -
src/PickerInput/Selector/SingleSelector/index.tsx中 onClear/onChange 的调用时机与副作用顺序。 - 新增测试中使用的假定定时器与 locale 设置对 CI 稳定性的影响。
Possibly related issues
- #52473: DatePicker does not allow manual clear — 本 PR 在输入为空时显式调用 onChange/onClear,直接对应“手动清空未触发 onChange”的描述。
- react-component/picker#946 — 与本次改动相似,均在输入清空路径增加显式 onChange(null) 处理,目标一致。
Possibly related PRs
- react-component/picker#942 — 对清空行为的 onChange/onClear 传递进行类似修改,与本 PR 在实现上高度相关。
Suggested reviewers
- afc163
- zombieJ
诗语
🐰 退格轻敲风声短,字符随手散云端,
空白化作 null 一环,onChange 回声暖心间,
测试护航夜半看,清空今朝终可安。
Pre-merge checks and finishing touches
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | ⚠️ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title Check | ✅ Passed | 拉取请求标题"fix: trigger onChange when manually clearing input via select all + delete"清晰准确地描述了主要变更。标题具体说明了修复内容(通过选中所有文本后删除来手动清空输入时触发onChange回调),与提供的代码摘要中所有四个修改文件的核心目标保持一致。标题简洁明了,没有冗余信息,能够帮助开发人员快速理解此变更的主要作用。 |
| Linked Issues Check | ✅ Passed | 本次拉取请求的代码变更完全符合关联问题#52473的所有核心要求。问题要求允许通过选中所有文本并按Delete/Backspace键手动清空日期选择器输入,并确保此行为与清除按钮(×)相同、触发onChange回调、防止模糊焦点后日期重新出现、以及支持所有选择器模式。代码修改(useInputProps.ts中添加空输入检测、Input.tsx中处理已格式化和未格式化输入、SingleSelector/index.tsx中处理null值)和新增的11个全面测试套件直接解决了这些要求。测试覆盖了不同的选择器模式、allowClear配置选项以及手动清除与清除按钮的一致性验证。 |
| Out of Scope Changes Check | ✅ Passed | 所有代码变更均直接与问题#52473的修复目标相关,不存在超出范围的改动。四个修改文件(Input.tsx、SingleSelector/index.tsx、useInputProps.ts和manual-clear.spec.tsx)的变更都专注于实现手动清空输入功能。新增的测试仅验证手动清除行为及其与清除按钮的一致性,不涉及其他功能或特性的改动。代码摘要明确指出未对导出或公共实体签名进行任何改动,确保了后向兼容性。 |
✨ Finishing touches
- [ ] 📝 Generate docstrings
🧪 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 669467f4a215b4bde10fefd98b565291ec7d4220 and 81b32b68fc02f75b40bcb625a0aa950e189d2f02.
📒 Files selected for processing (1)
-
tests/manual-clear.spec.tsx(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/manual-clear.spec.tsx (1)
tests/util/commonUtil.tsx (3)
getDay(186-195)openPicker(78-87)waitFakeTimer(71-76)
🔇 Additional comments (3)
tests/manual-clear.spec.tsx (3)
8-16: 测试设置正确。使用假计时器固定时间点,并在测试后正确清理,这是测试日期选择器的标准做法。
67-86: 已修复:测试现在正确输入了部分值。此测试已根据之前的反馈进行了修正。第 80 行现在正确地输入了部分日期值 '2023-08',然后验证在 blur 时该值被重置为完整日期 '2023-08-01' 且不触发 onChange。测试描述与实际行为现在一致。
265-302: 优秀的对比测试!此测试很好地验证了手动清空和清除按钮行为的一致性。两个
onChange回调都被正确断言,确保两种清空方式产生相同的结果。这种对比测试对于保证功能等价性非常有价值。
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
Codecov Report
:white_check_mark: All modified and coverable lines are covered by tests.
:white_check_mark: Project coverage is 98.81%. Comparing base (0dadb0a) to head (81b32b6).
:warning: Report is 1 commits behind head on master.
Additional details and impacted files
@@ Coverage Diff @@
## master #947 +/- ##
=======================================
Coverage 98.80% 98.81%
=======================================
Files 65 65
Lines 2680 2691 +11
Branches 744 748 +4
=======================================
+ Hits 2648 2659 +11
Misses 29 29
Partials 3 3
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
- :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
@li-jia-nan / @afc163 / @zombieJ Can someone please take a look at this PR whenever you have time. Thank you!
@zombieJ Please review this
Bumping this up, incase missed it.
@gemini-code-assist Pls help to CR agaign.
@gemini-code-assist can you re-review the PR?
@zombieJ thanks for your suggestions. I have resolved those changes, can you please do a re-review whenever you get time? Thanks!
^ Bumping this up again, thanks for reviewing the PR