Repository navigation
[Input] Required message refactoring - Part 2 - #5400
Vincent Baaij (vnbaaij) wants to merge 8 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
✅ All tests passed successfully Details on your Workflow / Core Tests page. |
Summary - Unit Tests Code CoverageSummary
CoverageMicrosoft.FluentUI.AspNetCore.Components - 98.3%
Microsoft.FluentUI.AspNetCore.Components.Charts - 100%
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Single-selection required checks can reject initialized values, and custom validation fields are not revalidated after selection changes.
Review effort: Balanced
Findings: 4
Open (7)
Custom validation field is not notified of selection changes · New Required validation ignores bound listbox value · New Revalidate custom field after selection changes · New Required validation ignores bound single selection · New Remove empty lifecycle override and dead commented code · New Avoid DateTime.Now in deterministic provider tests · New Use a fixed date for deterministic provider tests · New
What changed in this PR
Refactors required-field messaging into shared input validation logic and extends it across composite controls.
Changes:
- Centralizes required-message generation, including model and resource messages.
- Wires composite inputs to outer validation expressions.
- Adds validation tests and updates snapshots.
| File | Description |
|---|---|
tests/Core/Components/TextInput/FluentTextInputTests.razor |
Tests model-derived required messages. |
tests/Core/Components/TextArea/FluentTextAreaTests.razor |
Tests default required message. |
tests/Core/Components/Switch/FluentSwitchTests.razor |
Tests required switch behavior. |
tests/Core/Components/Switch/FluentSwitchTests.FluentSwitch_Required.verified.razor.html |
Updates required snapshot. |
tests/Core/Components/Switch/FluentSwitchTests.FluentSwitch_ReadOnly.verified.razor.html |
Updates read-only snapshot. |
tests/Core/Components/Switch/FluentSwitchTests.FluentSwitch_LabelTemplate.verified.razor.html |
Updates label-template snapshot. |
tests/Core/Components/Switch/FluentSwitchTests.FluentSwitch_Default.verified.razor.html |
Updates default snapshot. |
tests/Core/Components/Switch/FluentSwitchTests.FluentSwitch_Default_TrueValue.verified.razor.html |
Updates true-value snapshot. |
tests/Core/Components/Radio/FluentRadioTests.FluentRadio_LabelWidth.verified.razor.html |
Removes outer empty message. |
tests/Core/Components/Radio/FluentRadioTests.FluentRadio_LabelTemplate.verified.razor.html |
Removes outer empty message. |
tests/Core/Components/Radio/FluentRadioTests.FluentRadio_Label.verified.razor.html |
Removes outer empty message. |
tests/Core/Components/Radio/FluentRadioTests.FluentRadio_HorizontalOrientation.verified.razor.html |
Removes outer empty message. |
tests/Core/Components/Radio/FluentRadioTests.FluentRadio_Default.verified.razor.html |
Removes outer empty message. |
tests/Core/Components/Radio/FluentRadioGroupTests.razor |
Tests required radio groups. |
tests/Core/Components/Radio/FluentRadioGroupTests.FluentRadioGroup_WithChildContent.verified.razor.html |
Updates child-content snapshot. |
tests/Core/Components/Radio/FluentRadioGroupTests.FluentRadioGroup_Items.verified.razor.html |
Updates items snapshot. |
tests/Core/Components/Radio/FluentRadioGroupTests.FluentRadioGroup_Default.verified.razor.html |
Updates default snapshot. |
tests/Core/Components/Number/FluentNumberTests.razor |
Tests required number input. |
tests/Core/Components/List/FluentSelectTests.razor |
Tests select validation paths. |
tests/Core/Components/List/FluentSelectTests.FluentSelect_Width_And_Height.verified.razor.html |
Updates size snapshot. |
tests/Core/Components/List/FluentSelectTests.FluentSelect_OptionFunctions.verified.razor.html |
Updates option snapshot. |
tests/Core/Components/List/FluentSelectTests.FluentSelect_Manual.verified.razor.html |
Updates manual snapshot. |
tests/Core/Components/List/FluentSelectTests.FluentSelect_Label.verified.razor.html |
Updates label snapshot. |
tests/Core/Components/List/FluentSelectTests.FluentSelect_GetOptionValue_DefaultWhenTypesAreDifferent.verified.razor.html |
Updates differing-types snapshot. |
tests/Core/Components/List/FluentSelectTests.FluentSelect_Enum.verified.razor.html |
Updates enum snapshot. |
tests/Core/Components/List/FluentSelectTests.FluentSelect_Default.verified.razor.html |
Updates default snapshot. |
tests/Core/Components/List/FluentListboxTests.razor |
Tests listbox validation paths. |
tests/Core/Components/List/FluentListboxTests.FluentListbox_OptionFunctions.verified.razor.html |
Updates option snapshot. |
tests/Core/Components/List/FluentListboxTests.FluentListbox_Manual.verified.razor.html |
Updates manual snapshot. |
tests/Core/Components/List/FluentListboxTests.FluentListbox_Label.verified.razor.html |
Updates label snapshot. |
tests/Core/Components/List/FluentListboxTests.FluentListbox_GetOptionValue_DefaultWhenTypesAreDifferent.verified.razor.html |
Updates differing-types snapshot. |
tests/Core/Components/List/FluentListboxTests.FluentListbox_Enum.verified.razor.html |
Updates enum snapshot. |
tests/Core/Components/List/FluentListboxTests.FluentListbox_Default.verified.razor.html |
Updates default snapshot. |
tests/Core/Components/List/FluentComboboxTests.razor |
Tests required combobox behavior. |
tests/Core/Components/List/FluentComboboxTests.FluentCombobox_OptionFunctions.verified.razor.html |
Updates event and message snapshot. |
tests/Core/Components/List/FluentComboboxTests.FluentCombobox_Manual.verified.razor.html |
Updates manual snapshot. |
tests/Core/Components/List/FluentComboboxTests.FluentCombobox_Label.verified.razor.html |
Updates label snapshot. |
tests/Core/Components/List/FluentComboboxTests.FluentCombobox_Enum.verified.razor.html |
Updates enum snapshot. |
tests/Core/Components/List/FluentComboboxTests.FluentCombobox_Default.verified.razor.html |
Updates default snapshot. |
tests/Core/Components/List/FluentAutocompleteTests.razor |
Tests composite validation forwarding. |
tests/Core/Components/List/FluentAutocompleteTests.FluentAutocomplete_Label.verified.razor.html |
Updates label snapshot. |
tests/Core/Components/List/FluentAutocompleteTests.FluentAutocomplete_Default_Items.verified.razor.html |
Updates items snapshot. |
tests/Core/Components/Field/FluentFieldTests.FluentField_MessageState-error.verified.razor.html |
Captures error text styling. |
tests/Core/Components/DateTimes/FluentTimePickerTests.razor |
Tests time-picker validation. |
tests/Core/Components/DateTimes/FluentDatePickerTests.razor |
Tests date-picker required behavior. |
tests/Core/Components/DateTimes/FluentCalendarTests.razor |
Tests calendar required behavior. |
tests/Core/Components/ColorPicker/FluentColorPickerInputTests.razor |
Tests required and model validation. |
tests/Core/Components/Checkbox/FluentCheckboxTests.razor |
Tests required checkbox behavior. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_Size-medium.verified.razor.html |
Updates medium snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_Size-large.verified.razor.html |
Updates large snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_Size-999.verified.razor.html |
Updates invalid-size snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_Size-[empty].verified.razor.html |
Updates empty-size snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_ShowIndeterminate.verified.razor.html |
Updates indeterminate snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_Shape-square.verified.razor.html |
Updates square snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_Shape-circular.verified.razor.html |
Updates circular snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_Shape-999.verified.razor.html |
Updates invalid-shape snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_Shape-[empty].verified.razor.html |
Updates empty-shape snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_LabelTemplate.verified.razor.html |
Updates label-template snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_EnableThreeState.verified.razor.html |
Updates three-state snapshot. |
tests/Core/Components/Checkbox/FluentCheckboxTests.FluentCheckbox_Default.verified.razor.html |
Updates default snapshot. |
src/Core/Components/TextInput/FluentTextInput.razor.cs |
Uses shared required condition. |
src/Core/Components/TextArea/FluentTextArea.razor.cs |
Uses shared required condition. |
src/Core/Components/Switch/FluentSwitch.razor.cs |
Adds required condition. |
src/Core/Components/Radio/FluentRadioGroup.razor.cs |
Adds required selection condition. |
src/Core/Components/NumberInput/FluentNumberInput.razor.cs |
Uses shared required condition. |
src/Core/Components/List/FluentSelect.razor.cs |
Adds list validation expressions. |
src/Core/Components/List/FluentSelect.razor |
Connects field validation expression. |
src/Core/Components/List/FluentListbox.razor.cs |
Adds listbox validation expressions. |
src/Core/Components/List/FluentListbox.razor |
Connects field validation expression. |
src/Core/Components/List/FluentAutocomplete.razor.cs |
Forwards validation and messages. |
src/Core/Components/List/FluentAutocomplete.razor |
Configures inner text input validation. |
src/Core/Components/Field/FluentField.razor.cs |
Exposes field-identifier creation internally. |
src/Core/Components/Field/FluentField.razor |
Prioritizes validation messages. |
src/Core/Components/DateTime/FluentTimePicker.razor.cs |
Uses shared required condition. |
src/Core/Components/DateTime/FluentTimePicker.razor |
Forwards outer value expression. |
src/Core/Components/DateTime/FluentDatePicker.razor.cs |
Uses shared required condition. |
src/Core/Components/DateTime/FluentCalendar.razor.cs |
Uses localized shared condition. |
src/Core/Components/ColorPicker/FluentColorPickerInput.razor.cs |
Integrates shared required logic. |
src/Core/Components/ColorPicker/FluentColorPickerInput.razor |
Forwards outer value expression. |
src/Core/Components/Checkbox/FluentCheckbox.razor.cs |
Adds required condition. |
src/Core/Components/Base/FluentInputBase.Validation.cs |
Introduces shared validation helpers. |
examples/Tools/FluentUI.Demo.SampleData/Starship.cs |
Adds explicit required messages. |
examples/Demo/FluentUI.Demo.Client/Documentation/Components/Forms/Examples/BasicForm.razor.cs |
Leaves production date unset. |
examples/Demo/FluentUI.Demo.Client/Documentation/Components/Forms/Examples/BasicForm.razor |
Marks teleporter switch required. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Validation-field routing is inconsistent and the default required condition suppresses existing configured helper messages.
Review effort: Balanced
Findings: 1
Resolved since last review (7)
Required validation ignores bound single selection Revalidate custom field after selection changes Required validation ignores bound listbox value Custom validation field is not notified of selection changes Use a fixed date for deterministic provider tests Avoid DateTime.Now in deterministic provider tests Remove empty lifecycle override and dead commented code
Previously missed (4)
In code that hasn't changed since last review

Resolve ValidationFieldFor before falling back to FieldIdentifier

src/Core/Components/Base/FluentInputBase.Validation.cs:60
The default path ignores ValidationFieldFor and always uses the component's ValueExpression-based FieldIdentifier. For inputs such as FluentTextInput, the field renders validation for ValidationFieldFor, but this condition queries metadata/messages from a different property, so focus-out required text can fall back to the generic message instead of the custom model message. Resolve ValidationFieldFor before falling back to FieldIdentifier.
This issue also appears on line 64 of the same file.

Preserve ValidationFieldFor when forwarding text input expression

src/Core/Components/ColorPicker/FluentColorPickerInput.razor:6
Forwarding only ValueExpression drops a caller-supplied ValidationFieldFor, so the inner text input can display validation for a different model field than the wrapper requested. Pass the resolved ValidationFieldExpression instead.

Use resolved validation field for metadata and messages

src/Core/Components/ColorPicker/FluentColorPickerInput.razor.cs:47
This direct helper path still defaults to the outer component's FieldIdentifier, so a caller-supplied ValidationFieldFor is ignored when checking messages and reading its [Required] metadata. Resolve the same ValidationFieldExpression forwarded to the inner input and pass its identifier to both helper calls.

Forward resolved validation expression to the inner combobox

src/Core/Components/DateTime/FluentTimePicker.razor:9
Forwarding ValueExpression bypasses a caller-supplied ValidationFieldFor, so the inner combobox renders EditContext messages for the bound value rather than the explicitly selected validation field. Pass ValidationFieldExpression (ValidationFieldFor ?? ValueExpression) to preserve the wrapper's validation contract.
This issue also appears on line 49 of the same file.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

This part handles the Required message refactoring for composite inputs (AutoComplete, DatePicker, etc).
Can only be merged once Part 1 has been merged already. Then it will be substantially lesser changed files,,,