Closed sikora507 closed 4 months ago
The value on the select element is only in the browser. When the form the page is reloaded and any state from the client is overriden with state from the server, which doesn't mark any of the options as checked.
To Address
this you need to mark the option as checked explicitly when rendering from the server:
<option value="">Select classification ...</option>
<option checked="@(Model!.Classification == "Exploration")" value="Exploration">Exploration</option>
<option checked="@(Model!.Classification == "Diplomacy")" value="Diplomacy">Diplomacy</option>
<option checked="@(Model!.Classification == "Defense")" value="Defense">Defense</option>
If we wanted to improve this, we will need to do something like InputRadio
Thanks for contacting us.
We're moving this issue to the .NET 9 Planning
milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.
I'm working on covering this, but there's a strange behavior ...
In the form's original state in the sample app, it's true that the option value isn't retained on form submission.
As you point out @sikora507, if the Interactive Server render mode is applied to the component ...
@rendermode InteractiveServer
... the select retains the correct option state across form submissions.
However, the sample app has the Interactive Server render mode inherited via the Routes
component ...
<Routes @rendermode="InteractiveServer" />
There's clearly a difference for the browser's retention of the selected option.
I currently have the WIP lingo as ...
When the model property for the ship's classification (
Classification
) is set, the option matching the model is checked. For example,checked="@(Model!.Classification == "Exploration")"
for the classification of an exploration ship. The reason for explicitly setting the checked option is that the value of a<select>
element is only present in the browser. If the form is rendered on the server after it's submitted, any state from the client is overridden with state from the server, which doesn't ordinarily mark an option as checked. By setting the checked option from the model property, the classification always reflects the model's state. This preserves the classification selection across form submissions that result in the form rerendering on the server. In situations where the form isn't rerendered on the server, such as when the Interactive Server render mode is applied directly to the component, explicit assignment of the checked option isn't necessary.
I'm working on covering this, but there's a strange behavior ...
In the form's original state in the sample app, it's true that the option value isn't retained on form submission.
As you point out @sikora507, if the Interactive Server render mode is applied to the component ...
@rendermode InteractiveServer
... the select retains the correct option state across form submissions.
However, the sample app has the Interactive Server render mode inherited via the
Routes
component ...<Routes @rendermode="InteractiveServer" />
There's clearly a difference for the browser's retention of the selected option.
I currently have the WIP lingo as ...
When the model property for the ship's classification (
Classification
) is set, the option matching the model is checked. For example,checked="@(Model!.Classification == "Exploration")"
for the classification of an exploration ship. The reason for explicitly setting the checked option is that the value of a<select>
element is only present in the browser. If the form is rendered on the server after it's submitted, any state from the client is overridden with state from the server, which doesn't ordinarily mark an option as checked. By setting the checked option from the model property, the classification always reflects the model's state. This preserves the classification selection across form submissions that result in the form rerendering on the server. In situations where the form isn't rerendered on the server, such as when the Interactive Server render mode is applied directly to the component, explicit assignment of the checked option isn't necessary.
The repro app doesn't have interactive server on it, as far as I can see
https://github.com/sikora507/blazor-selectinput-issue/blob/main/BlazorForms/Components/App.razor#L16
When you use @InteractiveServer
it preserves the state because the code is running the component in stateful mode, the issue here appears when the component is stateless (a.k.a SSR).
The strange behavior 👽 that I'm referring to is WRT the Blazor sample app, not the repro app.
I was inheriting the interactive server render mode from the Routes
component for all of the app's form example components.
With the interactive server render mode assigned to the Routes
component, the select in that example forms component was losing its options setting on form submission using the old code that I had ... the code that @sikora507 shows in the OP. Now that I've updated the Blazor sample to your new approach that explicitly sets option from the model, it's all good now no matter if the interactive render mode is assigned or not or if it's assigned to the Routes
component. If that sounds like it shouldn't be happening (i.e., setting from the Routes
component with the original code not "remembering" the option), then I'll double-check and report back, possibly with a repro project.
AFAICT, the guidance paragraph above :point_up: is correct. However, I didn't get a reason in place, so I'll probably make one more change (to that last line of the paragraph) to incorporate this bit that you provided ...
When you use
@InteractiveServer
it preserves the state because the code is running the component in stateful mode
UPDATE: Done! I made an update to that line ...
In situations where the form isn't rerendered on the server, such as when the Interactive Server render mode is applied directly to the component, explicit assignment of the checked option from the model isn't necessary because Blazor preserves the state for the
<select>
element on the client.
I can change it if that's still not quite capturing the right sentiment.
Note that I'm still saying "directly to the component" because I didn't see preservation of the checked option via assigning the render mode to the Routes
component globally.
I think I have the same issue but the suggestion is not working for me.
<InputSelect @bind-Value="ProductDto.CategoryId" class="form-select">
<option value="0" disabled selected>-- Select Category --</option>
@foreach (var category in Categories)
{
<option checked="@(ProductDto.CategoryId == category.Id ? true: false)"
value="@category.Id">@category.Name
</option>
}
</InputSelect>
For OPTION-elements the attribute to use is SELECTED not CHECKED.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#selected
@MackinnonBuck is anything pending here? Should this be closed?
Yes, let's close this out for now. This issue can track the docs change, and if we get reports that the workaround is not sufficient, then we could use a new issue to track a framework change.
Is there an existing issue for this?
Describe the bug
I've been following input components documentation: https://learn.microsoft.com/en-us/aspnet/core/blazor/forms/input-components?view=aspnetcore-8.0
And I've created the application with starship form page:
After I provide all values and submit the form, the "Primary Classification" InputSelect component clears it's value, and when I try to click the Submit button again, I get the validation error. But the rest of the values are preserved. Only the one from InputSelect is cleared out.
The InputSelect component looks like this, straight from the docs:
The Submit method logs the values properly and I can see the Classification that i've selected.
But after the first post, the selected value is cleared.
I've provided the demo app on github: https://github.com/sikora507/blazor-selectinput-issue
The issue does not occur when I use
@rendermode InteractiveServer
Expected Behavior
After submitting the form, the selection should remain the same like for the rest of input controls
Steps To Reproduce
git clone git@github.com:sikora507/blazor-selectinput-issue.git
Exceptions (if any)
No response
.NET Version
8.0.100
Anything else?
IDE: JetBrains Rider 2023.3.1