Reputation: 14339
I am trying to use HTML5 data- attributes in my ASP.NET MVC 1 project. (I am a C# and ASP.NET MVC newbie.)
<%= Html.ActionLink("« Previous", "Search",
new { keyword = Model.Keyword, page = Model.currPage - 1},
new { @class = "prev", data-details = "Some Details" })%>
The "data-details" in the above htmlAttributes give the following error:
CS0746: Invalid anonymous type member declarator. Anonymous type members
must be declared with a member assignment, simple name or member access.
It works when I use data_details, but I guess it need to be starting with "data-" as per the spec.
My questions:
Upvotes: 339
Views: 158365
Reputation: 1250
In mvc 4 Could be rendered with Underscore(" _ ")
Razor:
@Html.ActionLink("Vote", "#", new { id = item.FileId, }, new { @class = "votes", data_fid = item.FileId, data_jid = item.JudgeID, })
Rendered Html
<a class="votes" data-fid="18587" data-jid="9" href="/Home/%23/18587">Vote</a>
Upvotes: 28
Reputation: 19
You can use it like this:
In Mvc:
@Html.TextBoxFor(x=>x.Id,new{@data_val_number="10"});
In Html:
<input type="text" name="Id" data_val_number="10"/>
Upvotes: -2
Reputation: 9474
Update: MVC 3 and newer versions have built-in support for this. See JohnnyO's highly upvoted answer below for recommended solutions.
I do not think there are any immediate helpers for achieving this, but I do have two ideas for you to try:
// 1: pass dictionary instead of anonymous object
<%= Html.ActionLink( "back", "Search",
new { keyword = Model.Keyword, page = Model.currPage - 1},
new Dictionary<string,Object> { {"class","prev"}, {"data-details","yada"} } )%>
// 2: pass custom type decorated with descriptor attributes
public class CustomArgs
{
public CustomArgs( string className, string dataDetails ) { ... }
[DisplayName("class")]
public string Class { get; set; }
[DisplayName("data-details")]
public string DataDetails { get; set; }
}
<%= Html.ActionLink( "back", "Search",
new { keyword = Model.Keyword, page = Model.currPage - 1},
new CustomArgs( "prev", "yada" ) )%>
Just ideas, haven't tested it.
Upvotes: 118
Reputation: 36413
It's even easier than everything suggested above. Data attributes in MVC which include dashes (-) are catered for with the use of underscore (_).
<%= Html.ActionLink("« Previous", "Search",
new { keyword = Model.Keyword, page = Model.currPage - 1},
new { @class = "prev", data_details = "Some Details" })%>
I see JohnnyO already mentioned this.
Upvotes: 61
Reputation: 4108
You can implement this with a new Html helper extension function which will then be used similarly to the existing ActionLinks.
public static MvcHtmlString ActionLinkHtml5Data(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes, object htmlDataAttributes)
{
if (string.IsNullOrEmpty(linkText))
{
throw new ArgumentException(string.Empty, "linkText");
}
var html = new RouteValueDictionary(htmlAttributes);
var data = new RouteValueDictionary(htmlDataAttributes);
foreach (var attributes in data)
{
html.Add(string.Format("data-{0}", attributes.Key), attributes.Value);
}
return MvcHtmlString.Create(HtmlHelper.GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, null, actionName, controllerName, new RouteValueDictionary(routeValues), html));
}
And you call it like so ...
<%: Html.ActionLinkHtml5Data("link display", "Action", "Controller", new { id = Model.Id }, new { @class="link" }, new { extra = "some extra info" }) %>
Simples :-)
edit
bit more of a write up here
Upvotes: 4
Reputation: 57502
This problem has been addressed in ASP.Net MVC 3. They now automatically convert underscores in html attribute properties to dashes. They got lucky on this one, as underscores are not legal in html attributes, so MVC can confidently imply that you'd like a dash when you use an underscore.
For example:
@Html.TextBoxFor(vm => vm.City, new { data_bind = "foo" })
will render this in MVC 3:
<input data-bind="foo" id="City" name="City" type="text" value="" />
If you're still using an older version of MVC, you can mimic what MVC 3 is doing by creating this static method that I borrowed from MVC3's source code:
public class Foo {
public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes) {
RouteValueDictionary result = new RouteValueDictionary();
if (htmlAttributes != null) {
foreach (System.ComponentModel.PropertyDescriptor property in System.ComponentModel.TypeDescriptor.GetProperties(htmlAttributes)) {
result.Add(property.Name.Replace('_', '-'), property.GetValue(htmlAttributes));
}
}
return result;
}
}
And then you can use it like this:
<%: Html.TextBoxFor(vm => vm.City, Foo.AnonymousObjectToHtmlAttributes(new { data_bind = "foo" })) %>
and this will render the correct data-* attribute:
<input data-bind="foo" id="City" name="City" type="text" value="" />
Upvotes: 667
Reputation: 624
I do not like use pure "a" tag, too much typing. So I come with solution. In view it look
<%: Html.ActionLink(node.Name, "Show", "Browse",
Dic.Route("id", node.Id), Dic.New("data-nodeId", node.Id)) %>
Implementation of Dic class
public static class Dic
{
public static Dictionary<string, object> New(params object[] attrs)
{
var res = new Dictionary<string, object>();
for (var i = 0; i < attrs.Length; i = i + 2)
res.Add(attrs[i].ToString(), attrs[i + 1]);
return res;
}
public static RouteValueDictionary Route(params object[] attrs)
{
return new RouteValueDictionary(Dic.New(attrs));
}
}
Upvotes: 0
Reputation: 2357
I ended up using a normal hyperlink along with Url.Action
, as in:
<a href='<%= Url.Action("Show", new { controller = "Browse", id = node.Id }) %>'
data-nodeId='<%= node.Id %>'>
<%: node.Name %>
</a>
It's uglier, but you've got a little more control over the a
tag, which is sometimes useful in heavily AJAXified sites.
HTH
Upvotes: 3