Reputation: 15503
If I am passing HtmlAttributes into a template, like this:
@Html.DisplayFor(m => m.FirstName, new { htmlAttributes = new { @class = "orangetxt strongtxt" } })
In my template, how would I inject these into my HTML:
<span @ViewData["htmlAttributes"]>@Model</span>
This almost works, but it does some pretty weird stuff, so I'm assuming this isn't the way to go.
I realize I can accomplish this with an HtmlHelper extension method to render the full HTML element (span, in this case) and pass in the attributes that way, but is there a way to just render attributes straight into an HTML element, like the above example?
Upvotes: 10
Views: 8299
Reputation: 15503
The below extension method will allow me to convert HtmlAttributes to a string:
public static MvcHtmlString RenderHtmlAttributes<TModel>(
this HtmlHelper<TModel> htmlHelper, object htmlAttributes)
{
var attrbituesDictionary = new RouteValueDictionary(htmlAttributes);
return MvcHtmlString.Create(String.Join(" ",
attrbituesDictionary.Select(
item => String.Format("{0}=\"{1}\"", item.Key,
htmlHelper.Encode(item.Value)))));
}
Then, to render them within the tag, I can just do this:
<span @Html.RenderHtmlAttributes(ViewData["htmlAttributes"])>@Model</span>
Upvotes: 9
Reputation: 96
Jerad Rose's answer is good, but I ran into couple of issues with it:
To address first issue, use HtmlHelper.AnonymousObjectToHtmlAttributes
.
Below is my modification of Jerad's method:
public static MvcHtmlString RenderHtmlAttributes(this HtmlHelper helper, object htmlAttributes)
{
if (htmlAttributes == null) return new MvcHtmlString(String.Empty);
var attrbituesDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
return new MvcHtmlString(String.Join(" ", attrbituesDictionary.Select(item => string.IsNullOrEmpty((string)item.Value) ? String.Format("{0}", item.Key) : String.Format("{0}=\"{1}\"", item.Key, helper.Encode(item.Value)))));
}
Upvotes: 5
Reputation: 24827
Try this instead,
@Html.DisplayFor(m => m.FirstName,
new { htmlAttributes = "class = orangetxt strongtxt"})
This will render a string, whereas your version did do weird stuff, rendered {
}
as part of the output.
Upvotes: 1
Reputation: 7476
DisplayFor()
is used to render the template that matches the property type.
Display templates are .cshtml files inside /DisplayTemplates folder which in turn is inside a view folder (i.e. any folder from Home, Shared or even a specific controller).
An example.
If you've a String.cshtml template like this inside /Views/Shared:
@model String
@if (string.IsNullOrEmpty(Model)) {
<span>(no string)</span>
}
else {
<span>@Model</span>
}
Every time you call DisplayFor()
for a string property:
DisplayFor(model => model.MyStringProperty);
It renders the template accordingly to the string's value. You can be more specific and put /DisplayTemplates inside a specific View folder and them only calls from those views are affected by the template.
In your case you can be even more specific and call DisplayFor()
with a particular template.
Suppose you've a template for a particular property, called MyPropertyTemplate.cshtml. You would call DisplayFor()
like this:
DisplayFor(model => model.MyProperty, "MyPropertyTemplate");
And them, inside that template you can have whatever HTML attributes you want.
@model MyProperty
<span class="orangetxt strongtxt">@MyProperty.ToString()</span>
PS: When it doesn't find a template I guess it only calls model.Property.ToString()
without additional html.
FYI: EditorFor()
, for example, works in a similar way but it uses /EditorTemplates folder.
Upvotes: 0