The Html. Editor() or Html. EditorFor() extension methods generate HTML elements based on the data type of the model object's property.
The advantages of EditorFor is that your code is not tied to an <input type="text" . So if you decide to change something to the aspect of how your textboxes are rendered like wrapping them in a div you could simply write a custom editor template ( ~/Views/Shared/EditorTemplates/string.
EditorFor does not allow for styling as there are no parameters for additional attributes. The reason for this is because the EditorFor doesn't always generate a single element as it can be overridden. To style a specific type of element you need to use the specific editor you want to use.
The HtmlEditor component is a client-side WYSIWYG text editor. The editor allows users to format text and integrate media elements into documents. The result can be exported to HTML or Markdown. Users can edit and customize content using the toolbar that can contain predefined and custom controls.
In MVC3, you can set width as follows:
@Html.TextBoxFor(c => c.PropertyName, new { style = "width: 500px;" })
I solved this by creating an EditorTemplate named String.ascx in my /Views/Shared/EditorTemplates folder:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<% int size = 10;
int maxLength = 100;
if (ViewData["size"] != null)
{
size = (int)ViewData["size"];
}
if (ViewData["maxLength"] != null)
{
maxLength = (int)ViewData["maxLength"];
}
%>
<%= Html.TextBox("", Model, new { Size=size, MaxLength=maxLength }) %>
In my view, I use
<%= Html.EditorFor(model => model.SomeStringToBeEdited, new { size = 15, maxLength = 10 }) %>
Works like a charm for me!
None of the answers in this or any other thread on setting HTML attributes for @Html.EditorFor were much help to me. However, I did find a great answer at
Styling an @Html.EditorFor helper
I used the same approach and it worked beautifully without writing a lot of extra code. Note that the id attribute of the html output of Html.EditorFor is set. The view code
<style type="text/css">
#dob
{
width:6em;
}
</style>
@using (Html.BeginForm())
{
Enter date:
@Html.EditorFor(m => m.DateOfBirth, null, "dob", null)
}
The model property with data annotation and date formatting as "dd MMM yyyy"
[Required(ErrorMessage= "Date of birth is required")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MMM yyyy}")]
public DateTime DateOfBirth { get; set; }
Worked like a charm without writing a whole lot of extra code. This answer uses ASP.NET MVC 3 Razor C#.
May want to look at Kiran Chand's Blog post, he uses custom metadata on the view model such as:
[HtmlProperties(Size = 5, MaxLength = 10)]
public string Title { get; set; }
This is combined with custom templates that make use of the metadata. A clean and simple approach in my opinion but I would like to see this common use case built-in to mvc.
I'm surprised no one mentioned passing it in "additionalViewData" and reading it on the other side.
View (with line breaks, for clarity):
<%= Html.EditorFor(c => c.propertyname, new
{
htmlAttributes = new
{
@class = "myClass"
}
}
)%>
Editor template:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<%= Html.TextBox("", Model, ViewData["htmlAttributes"])) %>
The problem is, your template can contain several HTML elements, so MVC won't know to which one to apply your size/class. You'll have to define it yourself.
Make your template derive from your own class called TextBoxViewModel:
public class TextBoxViewModel
{
public string Value { get; set; }
IDictionary<string, object> moreAttributes;
public TextBoxViewModel(string value, IDictionary<string, object> moreAttributes)
{
// set class properties here
}
public string GetAttributesString()
{
return string.Join(" ", moreAttributes.Select(x => x.Key + "='" + x.Value + "'").ToArray()); // don't forget to encode
}
}
In the template you can do this:
<input value="<%= Model.Value %>" <%= Model.GetAttributesString() %> />
In your view you do:
<%= Html.EditorFor(x => x.StringValue) %>
or
<%= Html.EditorFor(x => new TextBoxViewModel(x.StringValue, new IDictionary<string, object> { {'class', 'myclass'}, {'size', 15}}) %>
The first form will render default template for string. The second form will render the custom template.
Alternative syntax use fluent interface:
public class TextBoxViewModel
{
public string Value { get; set; }
IDictionary<string, object> moreAttributes;
public TextBoxViewModel(string value, IDictionary<string, object> moreAttributes)
{
// set class properties here
moreAttributes = new Dictionary<string, object>();
}
public TextBoxViewModel Attr(string name, object value)
{
moreAttributes[name] = value;
return this;
}
}
// and in the view
<%= Html.EditorFor(x => new TextBoxViewModel(x.StringValue).Attr("class", "myclass").Attr("size", 15) %>
Notice that instead of doing this in the view, you may also do this in controller, or much better in the ViewModel:
public ActionResult Action()
{
// now you can Html.EditorFor(x => x.StringValue) and it will pick attributes
return View(new { StringValue = new TextBoxViewModel(x.StringValue).Attr("class", "myclass").Attr("size", 15) });
}
Also notice that you can make base TemplateViewModel class - a common ground for all your view templates - which will contain basic support for attributes/etc.
But in general I think MVC v2 needs a better solution. It's still Beta - go ask for it ;-)
I think using CSS is the way to go. I wish I could do more with .NET coding, like in XAML, but in the browser CSS is king.
Site.css
#account-note-input {
width:1000px;
height:100px;
}
.cshtml
<div class="editor-label">
@Html.LabelFor(model => model.Note)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Note, null, "account-note-input", null)
@Html.ValidationMessageFor(model => model.Note)
</div>
Joe
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With