Checkbox Lists

By
Dave
Project
Published
28 Jun 2010 01:17
Last Modified
8 Dec 2012 16:42

Categories and tags are commonly used to classify blog posts. In order to specify the relevant categories and tags when creating and editing posts, two different approaches were taken, as shown below in Figure 1.

Checkbox list

Figure 1. Category checkbox list and comma-seperated tags

For the tags, a simple textbox can be used, with a controller action which parses a comma-seperated list. For the category list, a series of checkboxes can be rendered with the following view code:

<div>
    <% foreach (SelectListItem item in Model.CategoryList)
       {%>
    <input type="checkbox" class="checkbox" name="Categories"
        value="<%= item.Value%>"
        <%= item.Selected ? "checked=\"checked\"" : "" %> />
    <%= Html.Label(item.Text)%>
    <%} %>
</div>

In order to simplify the markup in the view, I created a simple HtmlHelper. The view code then becomes as follows:

<%= Html.CheckBoxList(Model.CategoryList, "Categories", new { Class = "checkbox" }, null)%>

The HtmlHelper is as follows:

public static string CheckBoxList(this HtmlHelper helper, List<SelectListItem> selectList,
    string name, object checkboxHtmlAttributes, object labelHtmlAttributes)
{
    StringBuilder stringBuilder = new StringBuilder();

    foreach (SelectListItem item in selectList)
    {
        TagBuilder tagBuilder = new TagBuilder("input");
        tagBuilder.MergeAttribute("type", "checkbox");
        tagBuilder.MergeAttribute("name", name);
        tagBuilder.MergeAttribute("value", item.Value);
        tagBuilder.MergeAttributes(new RouteValueDictionary(checkboxHtmlAttributes));

        if (item.Selected)
            tagBuilder.MergeAttribute("checked", "checked");

        // add checkbox
        stringBuilder.AppendLine(tagBuilder.ToString(TagRenderMode.SelfClosing));

        tagBuilder = new TagBuilder("label");
        tagBuilder.SetInnerText(item.Text);
        tagBuilder.MergeAttributes(new RouteValueDictionary(labelHtmlAttributes));

        // add label
        stringBuilder.AppendLine(tagBuilder.ToString());
    }

    return stringBuilder.ToString();
}

The model must include both the SelectList to pass the list of categories to the view, and an array of strings to post the selected values back to the controller, as follows:

public class MyModel
{
    ...
    public List<SelectListItem> CategoryList { get; set; }
    public string[] Categories { get; set; }
}

Regardless of which approach is used, the controller code looks like the following:

[HttpPost]
public ActionResult MyAction(MyModel model)
{
    if (model.Categories != null)
    {
        foreach (string item in model.Categories)
        {
            ...
        }
    }
    ...
}

Note that in both cases, only the checkboxes that are checked will have their values submitted to the controller, which is fine for this approach, as I (re)consruct the list of selected categories on each action.

Add Comment

*
*
*
Captcha
*
*Required