M Kenyon II
M Kenyon II

Reputation: 4274

Better user of Html Helpers to format text?

I have my profile model with these properties

public string FullName {get; set;}
public string Email {get; set;}

And I'd like the text to be displayed like this:

John P Doe ([email protected])

Currently I do this:

<div class="row section-head-bold">
    @Html.DisplayFor(modelItem => item.Profile.FullName)
    @Html.Raw(" (")@Html.DisplayFor(modelItem => item.Profile.Email)@Html.Raw(")")
</div>

Is there a better/cleaner way?

Upvotes: 0

Views: 648

Answers (1)

kent-id
kent-id

Reputation: 737

I believe the best way would be to create another property such as:

public string NameEmail {
    get {
        return String.Format("{0} ({1})", FullName, Email);
    }
}

However in case you need to use a separate style for FullName and Email, you can make your own custom HtmlHelper to achieve this. I have done this recently for a DateRangeDisplayFor which requires me to process the dates and display it with custom HTML structure and CSS classes. I have quickly modified the codes for your scenario and you can definitely modify this further to suit your needs.

HtmlHelper to display more complex HTML structure with custom CSS classes

public static MvcHtmlString NameEmailDisplayFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> property1,
    Expression<Func<TModel, TProperty>> property2,
    object htmlAttributes = null, bool useStyle = true)
{
    // Get the meta data of the properties
    ModelMetadata metadata1 = ModelMetadata.FromLambdaExpression(property1, htmlHelper.ViewData),
        metadata2 = ModelMetadata.FromLambdaExpression(property2, htmlHelper.ViewData);

    // get the data from db. If null, display N/A
    string name = metadata1 == null ? "N/A" : metadata1.Model.ToString();
    string email = metadata2 == null ? "N/A" : metadata2.Model.ToString();

    // build the HTML container tag and the sub-tags
    TagBuilder tag = new TagBuilder("label");    // parent wrapper
    var nameLbl = new TagBuilder("label");       // child label
    var emailLbl = new TagBuilder("label");      // child label

    // assign the model value to the labels
    nameLbl.InnerHtml = name;
    emailLbl.InnerHtml = email;

    // if useStyle is set to true, set custom CSS classes
    if (useStyle) {
        nameLbl.AddCssClass("label label-default");
        emailLbl.AddCssClass("label label-primary");
    }

    // apply inline HTML attributes (if any)
    if (htmlAttributes != null)
    {
        foreach (var attribute in htmlAttributes.ToDictionary())
            tag.Attributes.Add(attribute.Key, attribute.Value.ToString());
    }

    // add the child labels to the parent HTML wrapper
    tag.InnerHtml += nameLbl.ToString();
    tag.InnerHtml += emailLbl.ToString();

    // build the final MVC HTML string to be returned
    return new MvcHtmlString(tag.ToString(TagRenderMode.Normal));
}

And now you can use the HTML Helper in this way:

@Html.NameEmailDisplayFor(model => Model.Name, model => Model.Email)

Upvotes: 3

Related Questions