views:

1407

answers:

3

Is there a simple way to use the existing Html Helpers to generate a list of checkboxes with explicit values (as was possible in Beta)?

Example in Beta (possibly with MVC Contrib):

.CheckBox("Field", 6, new { value = 6}) would output:

<input id="Field1" type="checkbox" value="6" name="Field" />
<input id="Field2" type="hidden" value="6" name="Field" />

yet in RC2 I get:

<input id="Field1" type="checkbox" value="6" name="Field" />
<input type="hidden" value="false" name="Field" />

NB: I use a custom helper extension that generates unique HTML ids and sets the checked HTML attribute when appropriate

Besides using raw HTML and not using Html Helpers is there a way of setting checkboxes with explicit values? Looking at the Codeplex source code for RC2 there doesn't appear to be an easy way as .InputHelper() is marked private so you can't use it to help.

NB: There's more than one checkbox in the page to allow multiple selection, so the false value is of no use, as I need the values from the hidden field to know which items were ticked and which weren't (as non-checked checkbox values aren't posted - only the hidden fields are).

A: 

If the property that field maps to is of type Int, then false will be converted to 0, i think.

That's how you know how the box was checked or not.

changelog
A: 

As a workaround I've come up with the following based loosely on the RC2 sourcecode's InputHelper method, but adapted it to allow multiple values:

private static string CheckBoxWithValue(this HtmlHelper htmlHelper, string name, object value, bool isChecked, bool setId, IDictionary htmlAttributes)
     {
      const InputType inputType = InputType.CheckBox;
      if (String.IsNullOrEmpty(name))
      {
       throw new ArgumentException("null or empty error", "name");
      }

      var tagBuilder = new TagBuilder("input");
      tagBuilder.MergeAttributes(htmlAttributes);
      tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
      tagBuilder.MergeAttribute("name", name, true);
      string valueParameter = Convert.ToString(value, CultureInfo.CurrentCulture);

      if (isChecked)
      {
       tagBuilder.MergeAttribute("checked", "checked");
      }
      tagBuilder.MergeAttribute("value", valueParameter, true);
      if (setId) tagBuilder.GenerateId(name);

      // If there are any errors for a named field, we add the css attribute.
      ModelState modelState;
      if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState))
      {
       if (modelState.Errors.Count > 0)
       {
        tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
       }
      }
      var inputItemBuilder = new StringBuilder();
      inputItemBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));

      var hiddenInput = new TagBuilder("input");
      hiddenInput.MergeAttributes(htmlAttributes); 
      hiddenInput.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
      hiddenInput.MergeAttribute("name", name);
      if (setId)
      {
       hiddenInput.GenerateId(name);
      }
      hiddenInput.MergeAttribute("value", valueParameter);

      inputItemBuilder.Append(hiddenInput.ToString(TagRenderMode.SelfClosing));
      return inputItemBuilder.ToString();

     }

This relies on .ToString() your evaluate the object's value, but is adequate for my scenario where i'm using integers to represent options with the lookup done in the backend database. Note the setId boolean seems to just replace dots in the Html name with underscore characters. When using multiple checkboxes in HTML the IDs should be unique so I simply pass in the unique Id via htmlAttributes collection instead.

MVC-dot-net
I have wrapped this in another public helper method to set the isChecked Value from modelstate/viewdata in case you're wondering why this is marked as private.
MVC-dot-net
A: 

If you've recently gone from "normal" ASP.Net and started using MVC, then you may be very keen to avoid typing straight HTML, but in the MVC world it's not as much of an issue since there is no longer any viewstate and other issues to contend with. So feel free to just use straight HTML if you wish, especially if you're only dealing with integers (don't need to worry about javascript injection or anything).

Chris