Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is HtmlHelper's method to render htmlAttributes object?

I am building an Editor Template, which will accept htmlAttributes object.

Example is simple.

In main view I have something like

@Html.EditorFor(Function(x) x.SomeProperty, New With {.htmlAttributes = New With {.class = "form-control"}}). 

And in Editor Template I need class="form-control" attribute being written.

If within template I use something like @Html.TextBoxFor(Function(x) x, ViewData("htmlAttributes")), then everything is ok. But if I build a tag manually, I have no means to output htmlAttributes, i.e. I build <input type="text" {htmlAttributes should be here} />

Is there any public method to render HTML attributes within tag correctly?

like image 310
Dima Avatar asked Oct 08 '15 12:10

Dima


People also ask

What is the use of ActionLink in MVC?

ActionLink creates a hyperlink on a view page and the user clicks it to navigate to a new URL. It does not link to a view directly, rather it links to a controller's action.

What is HTML helper module?

The HTML helper is a mechanism for rendering HTML material in a view. An extension method is used to implement HTML helpers. HTML controls are rendered in the razor view by the HTMLHelper class.

What does HTMLHelper class do?

Helper class can create HTML controls programmatically. HTML Helpers are used in View to render HTML content. It is not mandatory to use HTML Helper classes for building an ASP.NET MVC application. We can build an ASP.NET MVC application without using them, but HTML Helpers helps in the rapid development of a view.


2 Answers

I'm not sure exactly what you're looking for here. Traditionally, an editor template will just pass-through the htmlAttributes. For example:

View

@Html.EditorFor(m => m.FooString, new { htmlAttributes = new { @class = "foo" } })

String.cshtml

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue.ToString(), ViewData["htmlAttributes"])

If you're asking about how to do something like set defaults that can then be overridden or added to by passing htmlAttributes. Then, you're pretty much on your own there. There's nothing existing in MVC to help you out (at least fully). However, I did write my own HtmlHelper extension to take care of this. I actually wrote a blog post to explain what this does and how to use it. I recommend you check it out, but I'll post the code here for completeness.

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

public static partial class HtmlHelperExtensions
{
    public static IDictionary<string, object> MergeHtmlAttributes(this HtmlHelper helper, object htmlAttributesObject, object defaultHtmlAttributesObject)
    {
        var concatKeys = new string[] { "class" };

        var htmlAttributesDict = htmlAttributesObject as IDictionary<string, object>;
        var defaultHtmlAttributesDict = defaultHtmlAttributesObject as IDictionary<string, object>;

        RouteValueDictionary htmlAttributes = (htmlAttributesDict != null)
            ? new RouteValueDictionary(htmlAttributesDict)
            : HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributesObject);
        RouteValueDictionary defaultHtmlAttributes = (defaultHtmlAttributesDict != null)
            ? new RouteValueDictionary(defaultHtmlAttributesDict)
            : HtmlHelper.AnonymousObjectToHtmlAttributes(defaultHtmlAttributesObject);

        foreach (var item in htmlAttributes)
        {
            if (concatKeys.Contains(item.Key))
            {
                defaultHtmlAttributes[item.Key] = (defaultHtmlAttributes[item.Key] != null)
                    ? string.Format("{0} {1}", defaultHtmlAttributes[item.Key], item.Value)
                    : item.Value;
            }
            else
            {
                defaultHtmlAttributes[item.Key] = item.Value;
            }
        }

        return defaultHtmlAttributes;
    }
}

Then, in your editor template (Date.cshtml in this example):

@{
    var defaultHtmlAttributesObject = new { type = "date", @class = "form-control" };
    var htmlAttributesObject = ViewData["htmlAttributes"] ?? new { };
    var htmlAttributes = Html.MergeHtmlAttributes(htmlAttributesObject, defaultHtmlAttributesObject);
}
@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue.ToString(), htmlAttributes)

UPDATE

I cannot use @Html.TextBox, but need to write manually <input type="text" {htmlAttributes should be here} />

Why? There's not really anything you can't do with the helper version. However, if you insist on going that route, you're going to have a hard time doing it with Razor. Assuming you can actually write it without Razor syntax errors, the code is going to be virtual unreadable. I'd suggest using TagBuilder and/or StringBuilder in pure C# to construct a string and then just make sure you return/set a variable of type MvcHtmlString:

var output = new MvcHtmlString(builder.ToString());

However, if you're going that far, it kind of negates the purpose of using an editor template, unless you're trying to override one of the default editor templates. Regardless, I'd recommend just creating your own HtmlHelper extension and then either using this directly in your view or using it in your editor template.

like image 136
Chris Pratt Avatar answered Nov 15 '22 06:11

Chris Pratt


Well for your case you can use static method that help you serialize your htmlAttributes to string that you need. I thik this is what you need:

public static string StringlifyHtmlAttributes(object htmlAttributes)
{
    string stringHtmlAttributes = String.Empty;
    foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(htmlAttributes))
    {
        stringHtmlAttributes += string.Format("{0}=\"{1}\" ", property.Name.Replace('_', '-'), property.GetValue(htmlAttributes));
    }
    return stringHtmlAttributes;
}
like image 45
teo van kot Avatar answered Nov 15 '22 08:11

teo van kot