How to set the htmlattributes cleanly on a razor page? - asp.net-mvc-3

I want to set up a text area on an MVC razor page like this:
#Html.TextAreaFor(e => e.Description)
But I have no idea of a tidy way to set the htmlattributes on the overload for this method on the page. Or perhaps I can do it on the model?
Knowing how to do it both ways would be really nice :-)

Something like,
#Html.TextAreaFor(e => e.Description, new { yourattribute = "Hello" })
This is an anonymous type. If you need to use language keywords, like class, escape it with an #:
#Html.TextAreaFor(e => e.Description, new { #class = "yourCSSclass", yourattribute = "Hello" })

Related

Strongly Typed ASP.NET MVC DropDownList Without SelectList

Is there a way to remove the selectlist parameter below and still use the HTML Helper? I like the strongly typed option, but use knockout.js quite a bit.
#Html.DropDownListFor(m => m.ProgramId, new SelectList(Enumerable.Empty<ProgramModel>()), new { data_bind = "enable: programs().length > 0, value: programId, options: programs, optionsText: 'Name', optionsValue: 'Id', optionsCaption: ' -- Choose Program -- ', event: { change: function(_,event) { getLicenseProductsForProgram() } }" })
Since Drop down List actually needs to have list of options, it requires the selectlist parameter. You can always pass an empty list to it though:
#Html.DropDownListFor(m => m.ProgramId, new List<SelectListItem>(), new { [the rest of your stuff] })
No, that's not possible. The standard DropDownList/DropDownListFor helpers expect an IEnumerable<SelectListItem> as second argument. Obviously there should be nothing preventing you from writing a custom helper, or custom editor template.

MVC3 Default value for HTML.TextAreaFor

I have an html.TextArea helper that I'd like to set a default.
#Html.TextAreaFor(model => model.CompletionCriteria,
new { rows = 5, cols = 70, #class = "celltext2",
#Value = ViewBag.CompletionCriteria,
#Text = ViewBag.CompletionCriteria })
The controller is setting the ViewBag.CompletionCriteria variable by querying the DBContext to get the default vaule for this given TextArea. The TextArea Value and Text properties are being set correctly, so the ViewBag is good, however the data doesn't display in the TextArea. I'm sure I'm just missing a property setting. Any ideas?
Remove the #Value and #Text attributes. It will automatically populate it, assuming it's set correctly and you're not using a strongly typed model. make sure it's spelled correctly in both your View and Controller.
In controller
Phone = model.UserPhoneNumber
In HTML
#Html.TextBoxFor(m => m.MobilePhone, new { #class = "form-control", #Value =Viewbag.UserPhoneNumber, data_mask = "phone" })
For Custom Attributes you can use like data_mask sample
it will render like data-mask ="phone"

MVC3 HTML Helper for large Text area

I have an html helper:
#Html.EditorFor(model => model.Description)
But it is too small for the data in that property of my Model. Descriptino is a 1000 character string. I need the user to be able to enter several lines of text and have it wrap in the HTML object. How do I do this?
Try
Html.TextAreaFor(model => model.Description, new {#cols="80" , #rows="4" })
Use:
#Html.TextAreaFor(model => model.Description)
// or a full option-list is:
#Html.TextAreaFor(model => model.Description,
rows, // the rows attribute of textarea for example: 4
columns, // the cols attribute of textarea for example: 40
new { }) // htmlAttributes to add to textarea for example: #class = "my-css-class"
Notice: you can use null instead of new { } for htmlAttributes but it is not recommended! It's strongly recommended that use a blank new { } -that represents a new object-
You can use EditorFor, but in that case it's better to define your own EditorTemplate for rendering your TextArea, using TextAreaFor or whatever it's needed.
The main difference between the TextAreaFor and EditorFor is that, if I've understood well how everything works, when using EditorFor, Templates are taken into account, while when using TextAreaFor you choose the HTML Input used for rendering.
Templates seems interesting, I'm just starting digging into writing my own.
Sounds like you're after Html.TextAreaFor.

Adding HtmlAttributes to template

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?
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>
Jerad Rose's answer is good, but I ran into couple of issues with it:
It does not not convert underscores to dashes in attribute names
It does not handle no-value attributes gracefully
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)))));
}
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.
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.

MVC3 ASP.NET; How to add value in input[type="text"]?

So currently, at my current employer we are using MVC3 ASP.NET with Razor. I think that is how you say it. Anyways, our input fields look something like this...
#Html.TextBoxFor(m => m.EmailAddress, new { #class = "text-box single-line" })
Now I understand what it is doing, don't need help on that. I need help on understanding how to place an value into that input field that it creates.
Anyone know how?
You are already doing that with the m => m.EmailAddress.
You just need to populate your Model with that data:
In your controller:
return View(new MyModel
{
EmailAddress = "foo#example.com",
});

Resources