Aspnetcore: Can't set custom 'value' attribute for a checkbox

Created on 17 Apr 2018  路  13Comments  路  Source: dotnet/aspnetcore

The following code in .html file works but not in a page (.cshtml)

<fieldset>
  <legend>Choose your interests</legend>
  <div>
    <input type="checkbox" id="coding" name="interest" value="coding" checked>
    <label for="coding">Coding</label>
  </div>
  <div>
    <input type="checkbox" id="music" name="interest" value="music">
    <label for="music">Music</label>
  </div>
</fieldset>
affected-few area-blazor c enhancement severity-minor

Most helpful comment

"Yes, we have repurposed value here and there may be an argument that we shouldn't in this case."

I don't think default attributes should be repurpsed under any circumstance, unless it's really a dealbreaker if they are not.

For example in Vue you still have the default attributes, but then you can hook them up with vue by typing a colon infront of them, like :value="myValue" or :data-something="something".

All 13 comments

What exactly is the problem? what is the error?

Coding Checkbox is not checked

I guess you should remove the value= stuff. What is the meaning of that?

@floreseken value is used when passing form data to a backend. Don't know if @dlr1 is using it though, his example is just copied from MDN.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox

I think he/she needs to provide more of the page's code or no one will be able to help.

I guess you should remove the value= stuff. What is the meaning of that?

@floreseken , value is a acceptable property for every input element, it's not the problem here.

He's question is about "checked" property that is not working as expected. If you create a

<input type="checkbox" checked />

It should be checked when you run on browser, and if you make it on blazor, are not checking. Take a look on above screen, first one is on Blazor page, the second one is on a pure html.

Image of coding

Edit: Even using checked="checked" not make checkbox selected.

@brunopbarrote Thanks.
I was trying to get a checkboxlist working and was not able to get that working anyway I tried. so like @AWulkan said, I copied html from that link to see if that would work.

The culprit is certainly value, but not sure why:

<input type="checkbox" checked /> Works
<input type="checkbox" value="coding" checked /> Does Not Work

Generated code:

base.BuildRenderTree(builder);
builder.OpenElement(7, "input");
builder.AddAttribute(8, "type", "checkbox");
builder.AddAttribute(9, "checked", "");
builder.CloseElement();
builder.AddContent(10, " Works\n            ");
builder.OpenElement(11, "input");
builder.AddAttribute(12, "type", "checkbox");
builder.AddAttribute(13, "value", "coding");
builder.AddAttribute(14, "checked", "");
builder.CloseElement();
builder.AddContent(15, " Does Not Work\n");

Edit:

And value is not actually rendering:

image

I'm going to take a shot at tracking this down in a few hours.

Ok, I still have a pretty shallow understanding of the codebase, but I've done some digging to discover what might be happening. I'm sure all of this is quite obvious for @SteveSandersonMS and @rynowak, and one of them will probably need to solve it.

Value Attribute Not Rendered

This happens because the value attribute is being treated specially for binding purposes. If you check out BrowserRenderer.ts you'll find this:

if (attributeName === 'value') {
  if (this.tryApplyValueProperty(toDomElement, renderTreeFrame.attributeValue(attributeFrame))) {
    return; // If this DOM element type has special 'value' handling, don't also write it as an attribute
  }
}

Checked State Not Reflected

Following the logic above, we can see that the checked state relies on the value attribute -- an empty string in the value attribute will cause the checkbox to render in the on state and a present string will render an off checkbox.

private tryApplyValueProperty(element: Element, value: string | null) {
  // Certain elements have built-in behaviour for their 'value' property
  switch (element.tagName) {
    case 'INPUT':
    case 'SELECT':
    case 'TEXTAREA':
      if (isCheckbox(element)) {
        (element as HTMLInputElement).checked = value === '';
      } else {
        (element as any).value = value;

So this:

<input type="checkbox" value="" /> Empty String
<br/>
<input type="checkbox" value="test" /> Present String 
<br/>
<input type="checkbox" checked /> No Value Attribute (checked attribute)
<br/>
<input type="checkbox" /> No Value Attribute (no checked attribute)

Will render this:

image

TL;DR: Some work needs to be done to support custom value attribute values on checkboxes.

Yes, we have repurposed value here and there may be an argument that we shouldn't in this case. However I'm not sure what you'd usefully do by setting a custom value attribute on a checkbox in a Blazor app, since that would normally only be used for an HTML form post, which is something people don't reasonably do in a SPA.

We'll have to give this further considation. Adding to backlog.

"Yes, we have repurposed value here and there may be an argument that we shouldn't in this case."

I don't think default attributes should be repurpsed under any circumstance, unless it's really a dealbreaker if they are not.

For example in Vue you still have the default attributes, but then you can hook them up with vue by typing a colon infront of them, like :value="myValue" or :data-something="something".

While this is a bug, a current workaround is to do something like this:
<input type="checkbox" id="coding" name="interest" bind=@coding>

This sets your coding variable to be bound to the input... i.e. when you click it, it updates your coding boolean variable... you can see this by putting @coding in the html page, like so:
<input type="checkbox" id="coding" name="interest" bind=@coding> @coding

Because "value" is being repurposed (which is a bad idea in my opinion) you cannot do the
<input value=@MyProperty onchange=@(eventArgs => { MyProperty = eventArgs.NewValue; DoSomethingElse(); }) /> @SteveSandersonMS suggestion (here) to have both a value and an onchange. There are also suggestions that we use the @bind and then do some kind of model pollution in the properties setters to fire your DoSomethingOnChange method. This works for simple models, but not good for lists of things.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

UweKeim picture UweKeim  路  3Comments

Kevenvz picture Kevenvz  路  3Comments

FourLeafClover picture FourLeafClover  路  3Comments

farhadibehnam picture farhadibehnam  路  3Comments

ipinak picture ipinak  路  3Comments