Inserting line breaks in DisplayName attributes - asp.net-mvc

In my ViewModel there is a property that needs a 2 line label but when I place a <br /> in the DisplayName attribute the HTML code is printed to the page instead of being interpreted as a line break. Is there a way to get a DisplayName to have a line break in it?
View:
<tr>
<td>
#Html.LabelFor(m => m.GrossGallons)
</td>
<td>
</td>
</tr>
ViewModel:
[DisplayName("Gross Gallons <br /> (Max: 6,000)")]
public decimal GrossGallons { get; set; }
Output trying to get:
Gross Gallons
(Max: 6,000)

There is a simple way of doing this - use \n instead of <br />, and use CSS to make it work.
Model:
[DisplayName("Gross Gallons\n(Max: 6,000)")]
public decimal GrossGallons { get; set; }
CSS:
label { white-space: pre-wrap; }
I would recommend making the CSS selector as specific as possible, so as not to catch other labels (in case you're using labels by hand elsewhere, where your source code may contain whitespace). For example, in bootstrap I would've applied this to label.control-label.
You could also attach a more specific style to that label only, and style only that class.
#Html.LabelFor(m => m.GrossGallons, new { #class = "multiline-label" })

I can think of a few options.
1) You could use #Html.Raw(). You can replace the string I have entered with a reference to a string.
#Html.Raw("Gross Gallons <br /> (Max: 6,000)");
1a) If you need to set it in the DisplayName attribute, then you might try using Html.Raw() but accessing the value through reflection. (Note: I haven't tried this, so don't know if it is possible)
2) You could use css styling to force the line to wrap where you want it to.
3) You could create a custom extension method or custom attribute to do this for you.

you can use #Html.Raw(), I think this is the most simple way.

It's not pretty, but you could use EditorTemplates and create a _layout.cshtml that all your Templates use. Then use this to pull/display the DisplayName:
<div class="form-group">
<label for="#ViewData.ModelMetadata.PropertyName">
#Html.Raw(ViewData.ModelMetadata.GetDisplayName())
</label>
#RenderBody()
#Html.ValidationMessageFor(x => x)
</div>
The serious drawback to this is you would have to create EditorTemplates for each of your types like this sample string.cshtml template:
#model string
#{
Layout = "_Layout.cshtml";
}
#Html.TextBoxFor(x => x, new { #class="form-control" })
A little off-topic but going this route allows me to encapsulate wrapping HTML around my form elements, so my forms in the views end up really simple like this:
<fieldset>
#Html.EditorFor(x => x.Email)
#Html.EditorFor(x => x.Address1)
#Html.EditorFor(x => x.Address2)
#Html.EditorFor(x => x.City)
</fieldset>

If use LabelFor(), another "possible" solution is to implement your own using the original source as a guide.
Replace
tag.SetInnerText(resolvedLabelText);
with
tag.InnerHtml = resolvedLabelText;

Related

Can I change the width of an EditorFor with data annotations?

There's a few questions on similar topics. However, they don't actually address my issue.
DisplayFormat for TextBoxFor in MVC
Display a formatted date in an EditorFor()
ASP.NET MVC EditorFor DateTime
I've been searching and reading up and cannot find an answer to this.
I'm currently using this to format my input box:
#Html.TextBoxFor(modelItem => item.Quantity, new { style = "width: 30px;" })
From my model, I have the brief data annotation:
[Required, Range(1, 100)]
public int Quantity { get; set; }
So I get this:
When I use
#Html.EditorFor(modelItem => item.Quantity, new { style = "width: 30px;" })
I get this:
What I want is the scroll, but to format the width.
I'm wondering, is there a way to format the width of an EditorFor with data annotations? If not, what is the easiest way to make such a format, to avoid repetition.. bootstrap, css? I'm not happy with the inline styling.
From the comments, your using MVC-4. You cannot pass html attributes to the EditorFor() method unless your using MVC-5.1 or higher (refer the release notes - the section on Bootstrap support for editor templates)
One option is to use the TextBoxFor() method and pass type="number" to render the browsers numeric control
#Html.TextBoxFor(m => m.Quantity, new { type = "number ", style = "width: 30px;" })
Another would be to create a custom EditorTemplate (say _NumericControl.cshtml)
#model System.Int32
#Html.TextBoxFor(m => m, new { type = "number ", style = "width: 30px;" })
and call it using #Html.EditorFor(m => m.Quantity, "_NumericControl")
but this would really only be of any real benefit if the template were also to include other html elements, for example #Html.LabelFor(m => m) and #Html.ValidationMessageFor(m => m) and perhaps even the associated button so that the EditorFor() method renders all elements.

Applying CSS class to Html.DisplayFor (ASP.NET MVC)

Am new to MVC, am am trying to apply CSS styles to Html.DisplayFor helper inside my template file: Shared>>EditorTemplate>>Contacts.cshtml. Below is my code:
#model People.Contacts
<div>
#Html.DisplayNameFor(m => m.Name) <span class="myclass">#Html.DisplayFor(m => m.FirstName) #Html.DisplayFor(m => m.LastName)</span></div>
and my css class outside this template looks like this:
.myclass{font:italic bold;}
Html.DisplayFor does not support passing HTML attributes, including class/style. At it's most basic it merely renders the value, without any HTML, and with editor/display templates, it just renders whatever's in the template.
First, if you have EditorTemplates\Contacts.cshtml, that will actually never be used by DisplayFor. For DisplayFor you need a separate template in Views\Shared\DisplayTemplates. As its name implies EditorTemplates is used by EditorFor.
Either DisplayFor or EditorFor are basically the same as calling Html.Partial. There's just some additional logic to deal with a specific model property and look by default in DisplayTemplates/EditorTemplates for the view. That said, you can pass additional data to them the same as you would with a partial, via ViewData.
For example, if you were to call #Html.DisplayFor(m => m.FirstName, new { #class = "myclass" }), then nothing would happen by default, but you would have a value of "myclass" in ViewData["class"]. You could then use that to modify a part of your template. For example:
Views\Shared\DisplayTemplates\Contacts.cshtml
<span #(ViewData["class"] != null ? "class='" + ViewData["class"] + "'" : string.Empty)>
#ViewData.TemplateInfo.FormattedModelValue
</span>
That checks to see if ViewData["class"] has a value, and if so, adds a class attribute with that value to the span.
As a different solutions you can use Html.DisplayFor in <Label> tag
<label class="control-label"> #Html.DisplayNameFor(p => p.HeadLine)</label>

How to get html5 attributes and values into mvc HiddenFor

I have following hidden input:
<input type="hidden" class="deleted" name="Deleted" data-id="#Model.Id" value="#Model.Deleted" />
I was wanting to convert this to the MVC helper HiddenFor.
Got this far:
#Html.HiddenFor(x => x.Deleted, new { #class="deleted" })
So that covers the class. I also need the data-id attribute and value.
Tried to add the data-id as:
#Html.HiddenFor(x => x.Deleted, new { #class="deleted", data-id="#Model.Id" })
Well the helper doesn't seem to like the hyphen in the data-id.
So how to get it in there?
Also how to get the value="#Model.Deleted" in there also?
Use _ and MVC will convert that to - when rendering.
Also you do not need the # infront of Model.Id. Remove the double quotes also. The below code should work.
#Html.HiddenFor(x => x.Deleted, new { #class="deleted", data_id=Model.Id })
And Why are you giving a css class to a hidden field ?
try
#Html.HiddenFor(x => x.Deleted, new { #class="deleted", "data-id"="#Model.Id" })

watermark text on textbox asp.net mvc razor

I am currently working on a ASP.NET MVC3 project and i created views to display contents , now i want to put watermark on #html.TextBoxFor() so i tried [Display(Prompt="WaterMarkText")],but its not working in IE8 and working well in Google chrome
Please help me to put watermark ..
here is my code
[Display(Prompt = "Scheme", Name = "Scheme")]
[Required(ErrorMessage = "*")]
public string name { get; set; }
view
<td>
#Html.LabelFor(model => model.scheme.name)
</td>
<td>
#Html.EditorFor(model => model.scheme.name)
</td>
<td>
#Html.ValidationMessageFor(model => model.scheme.name)
</td>
The Prompt parameter in the Display attribute just adds a "placeholder" attribute to the rendered input tag, like this:
<input type="text" placeholder="WaterMarkText" />
IE8 doesn't support the placeholder attribute, so you need to use javascript or CSS to achieve the same. You can do it with jQuery and this: http://www.standardista.com/html5-placeholder-attribute-script/

MVC partial views (or editor templates): append index to input name for multiple use of form?

How can I add an index, to input names and ids in forms that are used multiple times in one view?
I have created a form for photo rotator that provides the ability to edit a context-specific caption for each photo (billboard). I need to be able to include multiple instances of the form fields for this so the admins can edit all of the captions for a rotator's set of photos in one view, and so I need a way to keep ids and field names unique.
Editor templates automatically add a prefix, but when I loop over the photos like this:
<% foreach (var billboard in Model.Billboards ) { %>
<%: Html.EditorFor(x => billboard, "BillboardForm")%>
<% } %>
It simply adds "billboard_" as the prefix, which doesn't solve my problem.
I'd like to append the rotator id billboard id to the end of each input name and id:
<form action="/Rotators/Edit/5" method="post">
<input id="billboard_21_RotatorId" name="billboard_21_RotatorId" type="hidden" value="5" />
<input id="billboard_21_ImageId" name="billboard_21_ImageId" type="hidden" value="19" />
<label for="billboard_21_Title">Title</label>
<textarea cols="20" id="billboard_21_Title" name="billboard_21_Title" rows="2">Title</textarea>
<label for="billboard_21_Caption">Caption</label>
<textarea cols="20" id="billboard_21_Caption" name="billboard_21_Caption" rows="2">This is the caption</textarea>
<select id="billboard_21_TopicId" name="billboard_21_TopicId">
<option value="1">1st option</option>
</select>
</form>
Any easy way to do this??
plz download this sampel code from steve sanderson's blog post. it does not directly relate to your question. But in demo project you will find BeginCollectionItem html helper that is changing the prefix scope for input or series of inputs. This can give u a starting point
Edit:
in ur editor template u can use following method from steve's code like
using(Html.BeginHtmlFieldPrefixScope("BillBoard" + Model.ID.ToString())){
<label>Image<label>
#Html.TextBoxFor(x=>x.Image)
<label>Caption</label>
#Html.TextBoxFor(x=>x.Caption)
}
if ID is property of your model and has value e.g 4 then u will have html like
<label>Image</label>
<input name = "BillBoard4.Image" .../>
<label>Caption</label>
<input name = "BillBoard4.Caption" .../>
Note: The features used below may not have existed 4 years ago...
Firstly, you don't have to use beestings any more, the # syntax used
in the Razor examples is far cleaner.
The method you're calling is in System.Web.Mvc.Html.EditorExtensions:
public static MvcHtmlString EditorFor<TModel, TValue>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression
)
...
Your approach:
#foreach (var billboard in Model.Billboards ) {
#Html.EditorFor(x => billboard, "BillboardForm")
}
The body of expression x => billboard is a ConstantExpression.
This approach results in the appropriate scope applying in the EditorTemplate:
#for (var i = 0; i < Model.BillBoards.Count(); i++)
{
#Html.EditorFor(x => Model.BillBoards[i], "BillboardForm")
}
If Model.BillBoards is an array, the expression x => Model.BillBoards[i] can be described as
SimpleBinaryExpression{NodeType:ArrayIndex}(
Left: ConstantExpression,
Right: ConstantExpression
)
If Model.BillBoards is an IList<T>, the expression x => Model.BillBoards[i] can be described as
InstanceMethodCallExpressionN(
Method:RuntimeMethodInfo(IList<T>.get_Item (Int32 index)),
Object:PropertyExpression(ConstantExpression),
Arguments:[ConstantExpression]
)
The overloads of EditorFor() that accept Expressions check the expression body's Type and NodeType and construct the scope accordingly.
This code should be equivalent if you don't have anything else inside the loop:
#Html.EditorFor(x => Model.BillBoards, "BillboardForm")
If you only have a read-only view and an editing view, you can rename your templates and remove the second parameter. Assuming BillBoard is your Model class, rename BillboardForm.cshtml to EditorTemplates/BillBoard.cshtml, then change the code to
#Html.EditorFor(x => Model.BillBoards)

Resources