Skip to content

Fix binding <select> to a null value #23221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 22, 2020

Conversation

SteveSandersonMS
Copy link
Member

@SteveSandersonMS SteveSandersonMS commented Jun 22, 2020

This comes out of investigating #13440. The original issue, #13440, no longer repros in 3.1.x. However some of the later comments on the issue are reporting a different problem that does still repro.

Specifically, how do you have a <select> and bind it to a property whose value is sometimes null, for example a nullable-enum value?

This is unfortunately quite a problematic scenario because of a historical quirk in HTML. For any <option> that has no value attribute, the value is considered to be the text content of the option. This is a huge mess because (1) it takes away the only chance we had for representing the idea of a null value (not an empty string), and (2) it leads to completely unpredictable behavior because the text content might or might not happen to match up with a known server-side value depending on the user's current locale.

So since we have no way to have a true null-valued <option>, the closest we can do is to forget about distinguishing null from empty-string, and ensure that empty-string can round-trip in a binding and is treated as null on the .NET side, at least in the case of a nullable enum.

As it happens, our binding code that parses an incoming value as a nullable enum already treats string.Empty as null, so all that remains is accepting a rendered null value (represented by the removal/absence of the parent <select>'s value attribute) as mapping back to the empty-string <option>.

I'm not happy with the fact that we can't really have proper null values, but without either (1) going back to 1995 or (2) piling hacks upon hacks to fight against the browser's default behavior, this is the closest I think we can get.

@SteveSandersonMS SteveSandersonMS added the area-blazor Includes: Blazor, Razor Components label Jun 22, 2020
@SteveSandersonMS SteveSandersonMS requested a review from a team June 22, 2020 14:49
@pranavkm
Copy link
Contributor

going back to 1995

Should we bring that up in sprint planning?

// So, the most plausible 'null' equivalent is an empty string. It's unfortunate that people can't
// write <option value=@someNullVariable>, and that we can never distinguish between null and empty
// string in a bound <select>, but that's a limit in the representational power of HTML.
element.value = value || '';
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

@guardrex guardrex Jun 22, 2020

Choose a reason for hiding this comment

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

Is it more general tho than just forms validation? Seems like a binding topic subject that we could cross-link to from the forms validation topic.

Copy link
Contributor

@guardrex guardrex Jun 22, 2020

Choose a reason for hiding this comment

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

Well ... we already have radio buttons covered there, so I suppose that's fine. I'll look at cross-linking this the other way. I'll cross-link from the binding topic to the forms validation topic for the new section the same way that we do for radio button coverage.

@mrpmorris
Copy link

mrpmorris commented Jul 14, 2020

Would it be possible to set a marker attribute on the <option> when we try to set the value to @null, and in the Blazor code detect that and use null?

@guardrex
Copy link
Contributor

@mrpmorris ... You'll need to open a new issue (or comment on an existing open issue). The team doesn't work off of closed issue or closed PR comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants