Using Html Helper and Lambda expression for creating dropdown list and applying attributes on options tag of dropdown list
Traditional way of doing it.
Instead of iterating through and attaching attributes inside foreach look
We can do like below
It will output the select list with option tag and attribute on each option tag
Private method copied from mvc built in helper to generate option attribute
Utility function to get property name
Traditional way of doing it.
<select name="listbox" id="listbox">
@foreach (var item in Model)
{
<option value="@item.UserRoleId" data-name="@item.Name" data-class="@item.ClassName">
@item.UserRole
</option>
}
</select>
Instead of iterating through and attaching attributes inside foreach look
We can do like below
@Html.DropDownList(x => x.ReportName, Model.AvailableReports, x => x.TextField, x => x.NameField, "-- Select --",
new Dictionary<string, Expression<Func<ReportSummaryModel, object>>>{ {"data-name", x => x.ReportActualName}, {"data-class", x => x.ReportClassName}})
It will output the select list with option tag and attribute on each option tag
Output
var s = new string();
<select>
<option>--Select--</option>
<option value="1" data-name="NameA" data-class="classA">A</option>
<option value="2" data-name="NameB" data-class="classB">B</option>
<option value="3" data-name="NameC" data-class="classC">C</option>
<option value="4" data-name="NameD" data-class="classD">D</option>
</select>
Generic Tempelate
DropDownList<TPageModel, TSelectListModel, TProperty>
- TPageModel : Model of Page
- TSelectListModel : Model of Select List Item
- TProperty: Will be object so can use any type
public static MvcHtmlString DropDownList<TPageModel, TSelectListModel, TProperty>
(this HtmlHelper<TPageModel> htmlHelper,
Expression<Func<TSelectListModel, TProperty>> expression, IEnumerable<TSelectListModel> selectList,
Expression<Func<TSelectListModel, TProperty>> textField,
Expression<Func<TSelectListModel, TProperty>> valueField, string optionLabel, IDictionary<string,
Expression<Func<TSelectListModel, TProperty>>> optionsAttributes)
Parameters Descriptions
Expression<Func<TSelectListModel, TProperty>> expression
This is to provide the input property for which we are showing dropdown (Rename if want)IEnumerable<TSelectListModel> selectList
List of class of which text and value field you will be usingExpression<Func<TSelectListModel, TProperty>> textField
Provide the text field property from the TSelectListModelExpression<Func<TSelectListModel, TProperty>> valueField
Provide the value field property from the TSelectListModelstring optionLabel
Default Option Text for dropdown list boxIDictionary<string, Expression<Func<TSelectListModel, TProperty>>> optionsAttributes
This is to provide the attributes to be appear on option tag from the SelectListModelpublic static MvcHtmlString DropDownList<TPageModel, TSelectListModel, TProperty>(this HtmlHelper<TPageModel> htmlHelper, Expression<Func<TSelectListModel, TProperty>> expression, IEnumerable<TSelectListModel> selectList, Expression<Func<TSelectListModel, TProperty>> textField, Expression<Func<TSelectListModel, TProperty>> valueField, string optionLabel, IDictionary<string, Expression<Func<TSelectListModel, TProperty>>> optionsAttributes)
{
string name = ExpressionHelper.GetExpressionText(expression);
string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
string defaultValue = string.Empty;
ModelState modelState;
if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
{
if (modelState.Value != null)
{
defaultValue = (string)modelState.Value.ConvertTo(typeof(string), null /* culture */);
}
}
var listItemBuilder = new StringBuilder();
// Make optionLabel the first item that gets rendered.
if (optionLabel != null)
{
listItemBuilder.AppendLine(ListItemToOption(optionLabel, string.Empty, false, null));
}
/* Loop through each options
* Convert each ListItem to an <option> tag */
foreach (var listItem in selectList)
{
string text = listItem.GetType()
.GetProperties()
.Single(p => p.Name.Equals(ClassHelper.PropertyName(textField)))
.GetValue(listItem, null)
.ToString();
string value = listItem.GetType()
.GetProperties()
.Single(p => p.Name.Equals(ClassHelper.PropertyName(valueField)))
.GetValue(listItem, null)
.ToString();
bool isSelected = value.Equals(defaultValue);
var htmlAttributes = new Dictionary<string, string>();
foreach (var option in optionsAttributes)
{
string propertyName = ClassHelper.PropertyName(option.Value);
htmlAttributes.Add(option.Key, listItem.GetType()
.GetProperties()
.Single(p => p.Name.Equals(propertyName))
.GetValue(listItem, null)
.ToString());
}
listItemBuilder.AppendLine(ListItemToOption(text, value, isSelected, htmlAttributes));
}
var tagBuilder = new TagBuilder("select")
{
InnerHtml = listItemBuilder.ToString()
};
tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}
Private method copied from mvc built in helper to generate option attribute
internal static string ListItemToOption(string text, string value, bool isSelected, IDictionary<string, string> htmlAttributes)
{
var builder = new TagBuilder("option")
{
InnerHtml = HttpUtility.HtmlEncode(text)
};
if (value != null)
{
builder.Attributes["value"] = value;
}
if (isSelected)
{
builder.Attributes["selected"] = "selected";
}
if (htmlAttributes != null)
{
builder.MergeAttributes(htmlAttributes);
}
return builder.ToString(TagRenderMode.Normal);
}
Utility function to get property name
public class ClassHelper
{
public static string PropertyName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
{
var body = expression.Body as MemberExpression;
if (body == null)
{
body = ((UnaryExpression)expression.Body).Operand as MemberExpression;
}
return body.Member.Name;
}
}
No comments:
Post a Comment