Skip to content

feat(components): [time-picker] add save-on-blur prop#23531

Merged
rzzf merged 26 commits into
element-plus:devfrom
snowbitx:feat/time-picker-save-on-blur
Mar 5, 2026
Merged

feat(components): [time-picker] add save-on-blur prop#23531
rzzf merged 26 commits into
element-plus:devfrom
snowbitx:feat/time-picker-save-on-blur

Conversation

@snowbitx
Copy link
Copy Markdown
Contributor

@snowbitx snowbitx commented Jan 26, 2026

Please make sure these boxes are checked before submitting your PR, thank you!

  • Make sure you follow contributing guide English | (中文 | Español | Français).
  • Make sure you are merging your commits to dev branch.
  • Add some descriptions and refer to relative issues for your PR.

fixed: #23252
demo

Summary by CodeRabbit

  • New Features

    • Added a saveOnBlur option for TimePicker to keep the input empty on focus when no value is selected (default: true).
    • Exposed a cancel handler option for external use to allow cancelling tentative time edits.
  • Tests

    • Added tests verifying saveOnBlur behavior for single and range TimePicker modes to ensure focus preserves empty input when configured.
  • Documentation

    • Documented the new save-on-blur attribute in the TimePicker docs.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 26, 2026

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 26, 2026

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

Walkthrough

Adds a public saveOnBlur prop and related picker option handleCancel, updates display and spinner scroll logic, adds tests and docs so that when saveOnBlur is false, empty time inputs remain empty on focus and programmatic spinner adjustments don't trigger scroll handlers.

Changes

Cohort / File(s) Summary
Props & API
packages/components/time-picker/src/common/props.ts
Adds public prop saveOnBlur: { type: Boolean, default: true } and optional handleCancel?: () => void on PickerOptions.
Picker core
packages/components/time-picker/src/common/picker.vue
afterBlur now conditionally calls pickerOptions.value.handleCancel when time picker & !saveOnBlur; displayValue early-returns '' for empty time pickers when !saveOnBlur.
Spinner behavior
packages/components/time-picker/src/time-picker-com/basic-time-spinner.vue
Introduces ignoreScroll flags for hours/minutes/seconds; adjustSpinner sets/reset flags when !saveOnBlur; handleScroll ignores events while flagged to avoid reacting to programmatic updates.
Panel exposure
packages/components/time-picker/src/time-picker-com/panel-time-pick.vue
Exposes handleCancel via set-picker-option so external callers can access it.
Tests
packages/components/time-picker/__tests__/time-picker.test.tsx
Adds tests asserting inputs remain empty on focus for single and range modes when saveOnBlur is false.
Docs
docs/en-US/component/time-picker.md
Documents new save-on-blur attribute (Boolean, default true) in API table.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Input
  participant PickerLogic
  participant Spinner

  User->>Input: focus
  Input->>PickerLogic: request displayValue()
  Note right of PickerLogic: if isTimePicker && valueIsEmpty && !saveOnBlur
  PickerLogic-->>Input: return "" (empty)
  opt programmatic spinner adjust
    PickerLogic->>Spinner: adjustSpinner(type)
    Spinner->>Spinner: set ignoreScroll[type] = true (when !saveOnBlur)
    Spinner->>Spinner: requestAnimationFrame -> reset ignoreScroll[type]
  end
  User->>Spinner: user scroll
  Spinner->>PickerLogic: handleScroll(type)
  alt ignoreScroll[type] && !saveOnBlur
    PickerLogic-->>Spinner: early return (ignore)
  else
    PickerLogic-->>Spinner: process scroll event
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • rzzf
  • Dsaquel
  • btea

Poem

🐰
I nudged the clock but left it bare,
No borrowed minutes, no time to wear.
When focus comes, the input stays clean,
A blank-lit field, calm and serene.
Hop on, choose — the moment's seen.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding a save-on-blur prop to the time-picker component.
Description check ✅ Passed The description includes all checklist items marked as completed, references the linked issue (#23252), provides a demo link, and explains the new prop's usage with examples.
Linked Issues check ✅ Passed The changes directly address issue #23252 by implementing a save-on-blur prop that prevents auto-populating current time when focusing an empty input, providing explicit control over this behavior.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the save-on-blur feature: prop definition, picker logic updates, spinner adjustments, tests, and documentation updates are all directly related to the feature requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jan 26, 2026

Open in StackBlitz

pnpm add https://pkg.pr.new/element-plus@23531
npm i https://pkg.pr.new/element-plus@23531
yarn add https://pkg.pr.new/[email protected]

commit: 7e9dac9

@snowbitx snowbitx changed the title feat(components): [time-picker] prevent auto-fill on focus when empty feat(components): [time-picker] add save-on-blur prop Jan 26, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 26, 2026

🧪 Playground Preview: https://element-plus.run/?pr=23531
Please comment the example via this playground if needed.

@rzzf rzzf changed the title feat(components): [time-picker] add save-on-blur prop feat(components): [time-picker] add save-on-blur prop Jan 27, 2026
Copy link
Copy Markdown
Member

@rzzf rzzf left a comment

Choose a reason for hiding this comment

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

Could you update the documentation?

@snowbitx
Copy link
Copy Markdown
Contributor Author

Could you update the documentation?

Submitted, thanks!

Copy link
Copy Markdown
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

🤖 Fix all issues with AI agents
In `@docs/en-US/component/time-picker.md`:
- Line 78: Update the description for the save-on-blur prop in the Time Picker
docs: replace the current phrase "Whether to keep the input empty on focus when
no value is selected" with a corrected description such as "Whether to auto-fill
the input with the current time on focus when no value is selected" or "Whether
to save the time value on blur instead of keeping the input empty on focus" so
the wording matches the implemented default (saveOnBlur=true) and behavior;
ensure the table cell for the save-on-blur row (header symbol save-on-blur) is
updated accordingly and retains the default value true and type [boolean].

Comment thread docs/en-US/component/time-picker.md Outdated
@rzzf

This comment was marked as resolved.

@snowbitx

This comment was marked as resolved.

@rzzf

This comment was marked as resolved.

Copy link
Copy Markdown
Member

@Dsaquel Dsaquel left a comment

Choose a reason for hiding this comment

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

Sorry for the late review,

I think it's good, can we also propagate the effect until the user confirm the value ? Or it too complicated ?

@snowbitx
Copy link
Copy Markdown
Contributor Author

Sorry for the late review,

I think it's good, can we also propagate the effect until the user confirm the value ? Or it too complicated ?

Sorry for the oversight; I have already fixed it. Currently, when saveOnBlur is set to false, changes will only take effect if the user manually clicks the confirm button. If focus is lost without clicking the confirm button, the cancel action will be triggered.

Copy link
Copy Markdown
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 (1)
packages/components/time-picker/src/common/props.ts (1)

108-114: Clarify saveOnBlur description to include blur behavior.

Current text mentions focus only, but the implementation also changes blur-time commit/cancel flow.

✏️ Suggested wording
- * `@description` Whether to keep the input empty on focus when no value is selected.
+ * `@description` Whether to keep empty time input from auto-filling and avoid saving on blur unless explicitly confirmed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/components/time-picker/src/common/props.ts` around lines 108 - 114,
Update the JSDoc for the saveOnBlur prop in props.ts to mention both focus and
blur behavior: clarify that when true the input retains its displayed value on
focus and commits the tentative selection on blur, and when false the input can
be cleared on focus and tentative changes are discarded on blur (i.e.,
cancel/commit flow). Reference the saveOnBlur prop object to locate the
description to replace.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/components/time-picker/src/common/picker.vue`:
- Around line 298-302: The time-range panel defines handleCancel but never
exposes it, so afterBlur's call to pickerOptions.value.handleCancel?.() is a
no-op for timerange; in panel-time-range.vue, after defining handleCancel emit
the 'set-picker-option' event to register it (i.e. emit the set-picker-option
with the key 'handleCancel' and the handleCancel function) so pickerOptions
receives the handler and the afterBlur branch works the same as
panel-time-pick.vue.

---

Nitpick comments:
In `@packages/components/time-picker/src/common/props.ts`:
- Around line 108-114: Update the JSDoc for the saveOnBlur prop in props.ts to
mention both focus and blur behavior: clarify that when true the input retains
its displayed value on focus and commits the tentative selection on blur, and
when false the input can be cleared on focus and tentative changes are discarded
on blur (i.e., cancel/commit flow). Reference the saveOnBlur prop object to
locate the description to replace.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a162bb8 and 850ccc3.

📒 Files selected for processing (3)
  • packages/components/time-picker/src/common/picker.vue
  • packages/components/time-picker/src/common/props.ts
  • packages/components/time-picker/src/time-picker-com/panel-time-pick.vue

Comment thread packages/components/time-picker/src/common/picker.vue
Copy link
Copy Markdown
Member

@rzzf rzzf left a comment

Choose a reason for hiding this comment

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

There seems to be a bug:
after selecting a time and clicking the clear icon, the input is cleared and the focus correctly returns to the input.
However, once the input loses focus, the previously cleared value appears again.

repro

@rzzf
Copy link
Copy Markdown
Member

rzzf commented Mar 3, 2026

If I understand correctly, when save-on-blur is set to false, the modelValue should not change before the OK button is clicked, right?

Video
20260303-131328.mp4

@snowbitx
Copy link
Copy Markdown
Contributor Author

snowbitx commented Mar 3, 2026

If I understand correctly, when save-on-blur is set to false, the modelValue should not change before the OK button is clicked, right?

Video

Yes, that’s exactly the effect.

@Dsaquel
Copy link
Copy Markdown
Member

Dsaquel commented Mar 3, 2026

Thanks for your time, i ran into an issue:
demo :

  1. Clear.
  2. Open the time picker.
  3. Scroll into the time.
  4. Click outside.

Expected: the input should be cleared again but it's actually set the initial value.

@snowbitx
Copy link
Copy Markdown
Contributor Author

snowbitx commented Mar 4, 2026

demo

Thanks for pointing that out. I've fixed it.

@snowbitx snowbitx requested review from Dsaquel and rzzf March 4, 2026 10:38
Copy link
Copy Markdown
Member

@Dsaquel Dsaquel left a comment

Choose a reason for hiding this comment

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

Thank you 🫡

Comment thread packages/components/time-picker/src/time-picker-com/basic-time-spinner.vue Outdated
@rzzf
Copy link
Copy Markdown
Member

rzzf commented Mar 5, 2026

@snowbitx I optimized the options parameter signature of useOldValue. Could you take a look?

@snowbitx
Copy link
Copy Markdown
Contributor Author

snowbitx commented Mar 5, 2026

@snowbitx I optimized the options parameter signature of useOldValue. Could you take a look?

Okay.I see see

@rzzf
Copy link
Copy Markdown
Member

rzzf commented Mar 5, 2026

@snowbitx I optimized the options parameter signature of useOldValue. Could you take a look?

Okay.I see see

If you think it looks good, we can merge it. 🚀

@snowbitx
Copy link
Copy Markdown
Contributor Author

snowbitx commented Mar 5, 2026

@snowbitx I optimized the options parameter signature of useOldValue. Could you take a look?

Okay.I see see

If you think it looks good, we can merge it. 🚀

It looks good to me. I just have a small suggestion — would it be possible to replace any with unknown? What do you think? 😊

@snowbitx
Copy link
Copy Markdown
Contributor Author

snowbitx commented Mar 5, 2026

@snowbitx I optimized the options parameter signature of useOldValue. Could you take a look?

Okay.I see see

If you think it looks good, we can merge it. 🚀

Your approach to handling reactivity is more elegant. Thanks — I learned something from it. 😊

@rzzf
Copy link
Copy Markdown
Member

rzzf commented Mar 5, 2026

I just have a small suggestion — would it be possible to replace any with unknown? What do you think? 😊

Sure.

@rzzf rzzf enabled auto-merge (squash) March 5, 2026 14:07
@rzzf rzzf merged commit f695f8f into element-plus:dev Mar 5, 2026
14 of 15 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 5, 2026

@snowbitx Thanks for your contribution! ❤️

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

Projects

None yet

3 participants