Skip to content

Add DefaultValue parameter to BitInputBase (#8186)#12534

Merged
msynk merged 2 commits into
bitfoundation:developfrom
msynk:8186-blazorui-inputbase-defaultvalue
Jun 29, 2026
Merged

Add DefaultValue parameter to BitInputBase (#8186)#12534
msynk merged 2 commits into
bitfoundation:developfrom
msynk:8186-blazorui-inputbase-defaultvalue

Conversation

@msynk

@msynk msynk commented Jun 29, 2026

Copy link
Copy Markdown
Member

closes #8186

Summary by CodeRabbit

  • New Features

    • Added consistent uncontrolled-mode DefaultValue support across input controls (applies when Value isn’t bound), with updated demo parameter wiring.
  • Bug Fixes

    • Ensured default values are applied during initialization for calendar/date/time, OTP, tags, and other inputs.
    • Disabled inputs now reliably stop value updates, even when bypass logic is requested.
  • Documentation

    • Updated component demo metadata to reflect the unified default-value behavior.
  • Tests

    • Added/updated unit tests to verify defaults are honored when unbound and ignored when controlled.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 659f0420-9f93-4701-ac0f-86d585292499

📥 Commits

Reviewing files that changed from the base of the PR and between a4be720 and ea9e012.

📒 Files selected for processing (1)
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/TagsInput/BitTagsInputTests.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/TagsInput/BitTagsInputTests.cs

Walkthrough

DefaultValue is moved into BitInputBase<TValue> as shared uncontrolled-mode support, and input components now use SetDefaultValue() during initialization. Component demos and tests are updated to match the new behavior and API surface.

Changes

DefaultValue centralization in BitInputBase

Layer / File(s) Summary
BitInputBase: DefaultValue parameter and SetDefaultValue()
src/BlazorUI/Bit.BlazorUI/Components/Inputs/BitInputBase.cs
Adds DefaultValue [Parameter], DefaultValueHasBeenSet, parameter parsing, and SetDefaultValue(). Also changes disabled value updates to return immediately.
Input initialization uses SetDefaultValue()
src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/Rating/BitRating.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.razor.cs, src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.razor.cs, src/BlazorUI/Bit.BlazorUI.Extras/Components/PhoneInput/BitPhoneInput.razor.cs
Removes local DefaultValue parameters where they existed and calls SetDefaultValue() in initialization paths for the affected components.
Demo metadata updates
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/DemoPage.razor.cs, src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/...
Adds DefaultValue to shared input parameter metadata and removes or replaces component-specific DefaultValue entries in the input demos.
Tests for DefaultValue behavior
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/...
Adds ShouldRespectDefaultValue tests for Calendar, CircularTimePicker, DatePicker, DateRangePicker, OtpInput, TagsInput, and TimePicker. Refactors SearchBox tests, updates TextField trimming expectations, and changes the checkbox validation parameter type.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 A base class now knows the plan,
One default path across the land.
Inputs hop in with values new,
Demos and tests keep pace, too.
The warren hums in tidy tune—
One shared default, and off they zoom! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.63% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding DefaultValue support to BitInputBase.
Linked Issues check ✅ Passed The PR adds a DefaultValue parameter to BitInputBase for uncontrolled usage with OnChange, matching issue #8186.
Out of Scope Changes check ✅ Passed The additional component, demo, and test updates all support the new DefaultValue behavior and are in scope.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.razor.cs (1)

166-179: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Route DefaultValue through OTP normalization first.

This path writes the raw default into Value before any OTP-specific sanitization runs. With Length=4, a DefaultValue of "12345" leaves Value == "12345" while the rendered boxes show 1234; numeric OTPs also bypass the existing digit-only checks here. Normalize the default with the same length/type rules used for user input, then sync Value from the normalized slots so the public value matches the UI.

🤖 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 `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.razor.cs`
around lines 166 - 179, The OnInitialized flow in BitOtpInput is assigning
DefaultValue directly through SetDefaultValue without applying the OTP
normalization used for user input. Update the initialization path so the default
value is first sanitized and truncated according to Length and OTP type rules,
then use the normalized slots to populate Value and the input state. Keep the
fix localized around SetDefaultValue, Value, and the initialization setup in
BitOtpInput so the public value matches the rendered boxes.
src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.razor.cs (1)

330-341: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Normalize DefaultValue before seeding _hour and _minute.

SetDefaultValue() copies the raw TimeSpan?, but this component only renders CurrentValue?.Hours/?.Minutes and later rebuilds Value from those fields. A default like new TimeSpan(25, 30, 0) will render as 01:30 while Value still holds 25:30:00, then silently change on the first interaction. Route the default through the same time-of-day normalization this component uses for user input before storing it.

🤖 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
`@src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.razor.cs`
around lines 330 - 341, The initialization in
BitCircularTimePicker.OnInitialized seeds _hour and _minute from CurrentValue
after calling SetDefaultValue, but DefaultValue is not normalized to the
component’s time-of-day representation. Update SetDefaultValue and/or the
OnInitialized path so DefaultValue is routed through the same normalization used
for user input before assigning CurrentValue, then let _hour and _minute derive
from that normalized value. Use the BitCircularTimePicker component members
SetDefaultValue, CurrentValue, _hour, and _minute to keep the rendered time and
stored value consistent.
🧹 Nitpick comments (2)
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/DateRangePicker/BitDateRangePickerTests.cs (1)

1170-1172: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Don't couple this test to object identity.

Line 1170 only passes when the component keeps the exact same BitDateRangePickerValue instance around. The real contract here is the selected start/end dates, which you already assert on Lines 1171-1172, so the object-level equality check is overfitting the current implementation.

Suggested cleanup
-        Assert.AreEqual(defaultValue, component.Instance.Value);
         Assert.AreEqual(defaultValue.StartDate, component.Instance.Value!.StartDate);
         Assert.AreEqual(defaultValue.EndDate, component.Instance.Value!.EndDate);
🤖 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
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/DateRangePicker/BitDateRangePickerTests.cs`
around lines 1170 - 1172, The test in BitDateRangePickerTests is over-coupled to
object identity by asserting the component’s Value is the exact same
BitDateRangePickerValue instance as defaultValue. Remove the instance-equality
assertion and keep the contract focused on the selected dates by relying on the
StartDate and EndDate checks already present in the test.
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/DatePicker/BitDatePickerTests.cs (1)

1037-1049: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the Value-wins-over-DefaultValue case.

This only covers the happy path. The regression-prone part of the new BitInputBase.SetDefaultValue() contract is that DefaultValue must not overwrite an explicit Value, so please add an adjacent test that passes both parameters and asserts Value wins.

🤖 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
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/DatePicker/BitDatePickerTests.cs`
around lines 1037 - 1049, Add an adjacent test for BitDatePicker that covers the
Value-over-DefaultValue behavior in the new BitInputBase.SetDefaultValue()
contract. In BitDatePickerTests, render BitDatePicker with both Value and
DefaultValue set, then assert the component.Instance.Value remains the
explicitly provided Value and is not overwritten by DefaultValue. Use the
existing BitDatePickerShouldRespectDefaultValue test as the nearby reference
point and keep the new case focused on the Value-wins scenario.
🤖 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 `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.razor.cs`:
- Line 419: `BitTextField` is seeding `DefaultValue` without applying the
existing `Trim` behavior, so the uncontrolled initial value can keep surrounding
whitespace. Update `SetDefaultValue()` (or the path that assigns the initial
value in `BitTextField.razor.cs`) to normalize the seeded value the same way the
parsed path does when `Trim` is true, preserving the previous visible behavior.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/TagsInput/BitTagsInputTests.cs`:
- Around line 423-424: The test in BitTagsInputTests is asserting the
List<string> reference instead of the tag contents, so it fails if BitTagsInput
makes a valid defensive copy. Update the assertion on com.Instance.Value to
compare the sequence items (and keep the count check) so the test verifies the
emitted tags by value rather than object identity.

---

Outside diff comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.razor.cs`:
- Around line 330-341: The initialization in BitCircularTimePicker.OnInitialized
seeds _hour and _minute from CurrentValue after calling SetDefaultValue, but
DefaultValue is not normalized to the component’s time-of-day representation.
Update SetDefaultValue and/or the OnInitialized path so DefaultValue is routed
through the same normalization used for user input before assigning
CurrentValue, then let _hour and _minute derive from that normalized value. Use
the BitCircularTimePicker component members SetDefaultValue, CurrentValue,
_hour, and _minute to keep the rendered time and stored value consistent.

In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.razor.cs`:
- Around line 166-179: The OnInitialized flow in BitOtpInput is assigning
DefaultValue directly through SetDefaultValue without applying the OTP
normalization used for user input. Update the initialization path so the default
value is first sanitized and truncated according to Length and OTP type rules,
then use the normalized slots to populate Value and the input state. Keep the
fix localized around SetDefaultValue, Value, and the initialization setup in
BitOtpInput so the public value matches the rendered boxes.

---

Nitpick comments:
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/DatePicker/BitDatePickerTests.cs`:
- Around line 1037-1049: Add an adjacent test for BitDatePicker that covers the
Value-over-DefaultValue behavior in the new BitInputBase.SetDefaultValue()
contract. In BitDatePickerTests, render BitDatePicker with both Value and
DefaultValue set, then assert the component.Instance.Value remains the
explicitly provided Value and is not overwritten by DefaultValue. Use the
existing BitDatePickerShouldRespectDefaultValue test as the nearby reference
point and keep the new case focused on the Value-wins scenario.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/DateRangePicker/BitDateRangePickerTests.cs`:
- Around line 1170-1172: The test in BitDateRangePickerTests is over-coupled to
object identity by asserting the component’s Value is the exact same
BitDateRangePickerValue instance as defaultValue. Remove the instance-equality
assertion and keep the contract focused on the selected dates by relying on the
StartDate and EndDate checks already present in the test.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e1b55e57-f5db-49cf-95d1-0be5ec2c2783

📥 Commits

Reviewing files that changed from the base of the PR and between 83f9303 and a4be720.

📒 Files selected for processing (36)
  • src/BlazorUI/Bit.BlazorUI.Extras/Components/PhoneInput/BitPhoneInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/BitInputBase.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Rating/BitRating.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Components/DemoPage.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/BitChoiceGroupDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Dropdown/BitDropdownDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/NumberField/BitNumberFieldDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Rating/BitRatingDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TextField/BitTextFieldDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Toggle/BitToggleDemo.razor.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/Calendar/BitCalendarTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/Checkbox/BitCheckboxValidationTest.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/CircularTimePicker/BitCircularTimePickerTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/DatePicker/BitDatePickerTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/DateRangePicker/BitDateRangePickerTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/OtpInput/BitOtpInputTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/SearchBox/BitSearchBoxTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/TagsInput/BitTagsInputTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/TextField/BitTextFieldTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Components/Inputs/TimePicker/BitTimePickerTests.cs
💤 Files with no reviewable changes (10)
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Rating/BitRatingDemo.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Dropdown/BitDropdownDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/NumberField/BitNumberFieldDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Toggle/BitToggleDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/BitChoiceGroupDemo.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/TextField/BitTextFieldDemo.razor.cs

@msynk

msynk commented Jun 29, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai re-review

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

@msynk Re-reviewing the latest changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@msynk

msynk commented Jun 29, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai re-review

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

@msynk Re-reviewing the latest changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@msynk msynk merged commit 9c34dfb into bitfoundation:develop Jun 29, 2026
3 checks passed
@msynk msynk deleted the 8186-blazorui-inputbase-defaultvalue branch June 29, 2026 11:25
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.

The BitInputBase component is missing the DefaultValue parameter

1 participant