public static IHtmlString CheckBoxWithLabelFor<TModel, TProperty>(this HtmlHelper<TModel> helper,
Expression<Func<TModel, TProperty>> expression, string labelText, object htmlAttributes)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
object currentValue = metadata.Model;
string property = ExpressionHelper.GetExpressionText(expression);
var checkBox = new TagBuilder("input");
checkBox.AddCssClass("checkBoxWithLabel");
checkBox.GenerateId(property);
checkBox.Attributes["type"] = "checkbox";
checkBox.Attributes["name"] = property;
checkBox.Attributes["value"] = "true";
checkBox.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes),false);/*added false*/
var hidden = new TagBuilder("input");
hidden.Attributes["type"] = "hidden";
hidden.Attributes["name"] = property;
hidden.Attributes["value"] = "false";
if (Equals(currentValue, true))
{
checkBox.Attributes["checked"] = "checked";
}
var label = new TagBuilder("label");
label.AddCssClass("checkBoxLabel");
var htmlText = label.ToString().Replace("</label>", "");
htmlText += checkBox.ToString(TagRenderMode.SelfClosing);
htmlText += hidden.ToString(TagRenderMode.SelfClosing);
htmlText += labelText + "</label>";
return new HtmlString(htmlText);
AnonymousObjectToHtmlAttributes(htmlAttributes) only replaces "_" with "-". Whilst MergeAttributes expects a key/value type and is therefore ignoring the existing values. Cant change/cast the object HtmlAttributes to a Dictionary with IEnumerable, IDictionary etc. I think MergeAttributes should be in a loop to extract the key/values but not sure what starts the ball rolling?
I want class to have the initial htmlAttributes value "editableInNew editableInUpdate readonly" elements together with the "checkBoxWithLabel" added with .AddCssClass but cant get it work and I'm stumped.
You should not be attempting to manually generate your html in the helper, but rather making use of the built-in methods. Not only are you writing significantly more code that necessary, your not taking into account standard HtmlHelper features such as binding to ModelState
, client side validation etc which I assume you are not aware of. If you do want to do this manually, I recommend you study the source code first.
You should also change the signature of your helper to allow only boolean
properties.
public static IHtmlString CheckBoxWithLabelFor<TModel>(this HtmlHelper<TModel> helper,
Expression<Func<TModel, bool>> expression, string labelText, object htmlAttributes)
{
IDictionary<string, object> attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
// add the "checkBoxWithLabel" class
if (attributes.ContainsKey("class"))
{
attributes["class"] = "checkBoxWithLabel " + attributes["class"];
}
else
{
attributes.Add("class", "checkBoxWithLabel");
}
// build the html
StringBuilder html = new StringBuilder();
html.Append(helper.CheckBoxFor(expression, attributes));
html.Append(helper.LabelFor(expression, labelText, new { @class = "checkBoxLabel" }));
// suggest also adding the validation message placeholder
html.Append(helper.ValidationMessageFor(expression));
return MvcHtmlString.Create(html.ToString());
}