Add custom HTML attributes to generated controls - asp.net

I just want to add a placeholder for my generated input element.
This is what being generated
<input class="text-box single-line" data-val="true" data-val-required="The Username field is required." id="Username" name="Username" type="text" value="">
This is the code that generates HTML output
#Html.EditorFor(model => model.Username)
Of course I can just remove the generated code and write it by myself just including the necessary fields, however maybe it is possible to just pass some kind of parameter to EditorFor that will add placeholder attribute to it?

You can use #Html.TextBoxFor instead of #HtmlEditorFor and then write htmlAttributes like this:
#Html.TextBoxFor(model => model.Username, new { placeholder = "Username..." })

Try
#Html.EditorFor(m => model.Username, new { data_val_attribute = "value" });
Most of the helpers will have an overload that accepts an anonymous object as the last parameter for specifying attributes in the generated markup.

#Html.EditorFor(model => model.Username, new { placeholder = "Username..." }) should work, unless your model is not empty. Have you checked if your model is empty?

Related

Why do #Html.EditorFor and #Html.PasswordFor create different style boxes in MVC?

I am currently using the #Html.EditorFor HTML helper for the password field. I want to use the #Html.PasswordFor HTML helper instead.
I copied the current code and replaced #Html.EditorFor with #Html.PasswordFor.
CSHTML
This is the code:
#Html.EditorFor(x => x.Password, new { htmlAttributes = new { #class = "form-control k-textbox large", placeholder = "password", #id = "password", #autocomplete = "off" } })
#Html.PasswordFor(x => x.Pwd, new { htmlAttributes = new { #class = "form-control k-textbox large", placeholder = "password", #id = "password", #autocomplete = "off" } })
Rendered Output
The parameters are 100% the same, but these produce different style textboxes:
Note that #Html.EditorFor has validation and a placeholder as well, but #Html.PasswordFor doesn't; the later also has a different style. The validation spam element is also not a part of the textbox.
Generated HTML
Here is generated HTML code for #Html.EditorFor:
<input autocomplete="off" class="form-control k-textbox large text-box single-line password k-invalid" data-val="true" data-val-required=" " id="password" name="Password" placeholder="password" type="password" value="" aria-invalid="true">
Here is generated HTML code for #Html.PasswordFor:
<input data-val="true" data-val-required=" " htmlattributes="{ class = form-control k-textbox large, placeholder = password, id = password, autocomplete = off }" id="Pwd" name="Pwd" type="password" aria-invalid="true" class="k-invalid">
Model Definition
This is how I define those two fields in the model:
[Required(ErrorMessage = " ")]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required(ErrorMessage = " ")]
[DataType(DataType.Password)]
public string Pwd { get; set; }
What am I doing wrong here?
I can't tell you why the decision was made to treat these differently, but while the second parameter for these particular overloads of EditorFor() and PasswordFor() both accept an anonymous object, those objects actually represent different concepts.
Documentation
For EditorFor(), the second parameter is titled additionalViewData:
An anonymous object that can contain additional view data that will be merged into the ViewDataDictionary<TModel> instance that is created for the template.
For PasswordFor(), the second parameter is titled htmlAttributes:
An object that contains the HTML attributes to set for the element.
Explanation
In other words, you're operating at different levels here. When you set a property called htmlAttributes on your anonymous object for EditorFor() (i.e., additionalViewData), that's being parsed out as HTML attributes on your rendered element:
<input autocomplete="off" class="…" id="password" placeholder="password" … >
But when you set htmlAttributes on your anonymous object for PasswordFor() (i.e., htmlAttributes), that's being seen as an HTML attribute itself, as you can see in your HTML output:
<input htmlattributes="{ class = …, placeholder = password, id = password, autocomplete = off }" … >
Resolution
As a result, what you should be doing in elevating the htmlAttributes one level for your PasswordFor() call:
#Html.PasswordFor(x => x.Pwd, new { #class = "form-control k-textbox large", placeholder = "password", #id = "password", #autocomplete = "off" })
Which should render something like:
<input class="form-control k-textbox large" placeholder="password" id="password" autocomplete="off" … >
And with the CSS classes correctly set, you should also find that the presentation aligned.
The method signatures are slightly different.
public static System.Web.Mvc.MvcHtmlString PasswordFor<TModel,TProperty> (this System.Web.Mvc.HtmlHelper<TModel> htmlHelper,
System.Linq.Expressions.Expression<Func<TModel,TProperty>> expression,
object htmlAttributes);
public static System.Web.Mvc.MvcHtmlString EditorFor<TModel,TValue> (this System.Web.Mvc.HtmlHelper<TModel> html,
System.Linq.Expressions.Expression<Func<TModel,TValue>> expression,
object additionalViewData);
You don't need to wrap the PasswordFor attribute object in another object. What you have is:
#Html.EditorFor(m => m.Password, additionalViewData: new { htmlAttributes = new { ... } })
#Html.PasswordFor(m => m.Pwd, htmlAttributes: new { htmlAttributes = new { ... } })
It is simply:
#Html.PasswordFor(m => m.Pwd, new { #class = "..." })

Bootstrap required attribute in asp.net mvc razor view

I need to use the required attribute, so the field shoud not be empty
<input type="text" class="form-control" id="inputName" required>
in the razor view, more specifically in this example
#Html.EditorFor(model => model.exclure.libelle, new { htmlAttributes = new { #class = "form-control" } })
You can specify in htmlAttributes with TextBoxFor() this way:
#Html.TextBoxFor(m=>m.exclure.libelle,new{ #class = "form-control",required="required" })

Set the value of a Html.Hiddenfor

I have a form, to submit a bid.
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "Login" }))
{
#Html.ValidationSummary(true, "Gelieve alle velden in te vullen.")
#Html.LabelFor(m => m.Bid)<br />
#Html.TextBoxFor(m => m.Bid)<br />
#Html.LabelFor(m => m.Name)<br />
#Html.TextBoxFor(m => m.Name)<br />
#Html.LabelFor(m => m.Email)<br />
#Html.TextBoxFor(m => m.Email)<br />
#Html.HiddenFor(model => model.Car_id, new { value = ViewBag.car.id })
<input type="submit" value="Bied" class="button" />
}
And I want to set the value of the hiddenfor to the id of the car (I get it with the viewbag), but it doesn't work as seen here:
<input data-val="true" data-val-number="The field Car_id must be a number." data-val-required="Het veld Car_id is vereist." id="Car_id" name="Car_id" type="hidden" value="" /> <input type="submit" value="Bied" class="button" />
What is the correct way of doing this? Or are there other ways of passing a value to my code? I just need the Car_id in the Postback method..
even thought what Raphaël Althaus said is correct using the hard coded string is always a pain during refactoring. so try this
#{
Model.Car_id = ViewBag.car.id;
}
#Html.HiddenFor(model => model.Car_id)
by this way it will still be part of your model and lot more cleaner.
either Car_id is not a part of your model, then can't use HiddenFor, but have to use Hidden
something like
#Html.Hidden("Car_id", ViewBag.car.id)
assuming you've got something in ViewBag.car.id, the error you get seems to mean that there's nothing in there.
or it's part of your model and you shouldn't need a ViewBag. You should just set its value in the action related to that View.
#Html.HiddenFor(model => model.Car_id, htmlAttributes: new { #Value = ViewBag.Car_id })

ValidationSummary() not displaying when using RenderPartial in View

When I use
#{Html.RenderPartial("Login");}
inside my main view, the #Html.ValidationSummary() doesn't work, but when I copy the code from "Login" inside main view, it works.
Why is that, and how do I display validation messages from the partial view?
Here is partial view "Login":
#model NyNo.Models.LoginModel
#using (Html.BeginForm())
{
<fieldset>
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.TextBoxFor(m => m.UserName, new { #placeholder = "Username" })
#Html.ValidationMessageFor(m => m.UserName)
#Html.PasswordFor(m => m.Password, new { #placeholder = "Password" })
#Html.ValidationMessageFor(m => m.Password)
#Html.CheckBoxFor(m => m.RememberMe)
#Html.LabelFor(m => m.RememberMe, new { #class = "checkbox" })
<input type="submit" class="button" value="Log in" />
</fieldset>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Hope you understand, thanks!
Unfortunately, this cannot work. A Partial is just a string.
While RenderPartial actually 'writes' the partial markup rather than sending a string back to the View Generator, it does not rebind your View to a new model. If you want Validation Summary to work it must be bound to a model in your main View.
Your problem could be related to this (maybe you aren't showing the ViewData passed in the RenderPartial()): Pass Additional ViewData to an ASP.NET MVC 4 Partial View While Propagating ModelState Errors
I was having a similar issue and I solved it this way: ValidationSummary inside a partial view not showing errors

Render span tag with title attribute with ASP.NET MVC 3 Helpers

It's possible to add a HTML title attribute to an input tag like so:
#Html.TextBoxFor(model => model.Name, new { title = "Customer name" })
Is there a similar helper for static text? With #Html.DisplayFor(model => model.Name) I can render the text from a model property. How can I add HTML attributes so that I get a span tag rendered like this:
<span title="Customer name">ABC</span>
Custom html helper is probably the neatest solution.
public static MvcHtmlString SpanFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
{
var valueGetter = expression.Compile();
var value = valueGetter(helper.ViewData.Model);
var span = new TagBuilder("span");
span.MergeAttributes(new RouteValueDictionary(htmlAttributes));
if (value != null)
{
span.SetInnerText(value.ToString());
}
return MvcHtmlString.Create(span.ToString());
}
=>
#Html.SpanFor(model => model.Name, new { title = "Customer name" })
<span title="Customer name">#Model.Name</span>
If you are using #HTML.DisplayFor(model=>model.CustomerName) It will render as text, It will not shows any tag inside the values.
If you want to bind the "DisplayFor" using span , Use the below tag,
<span id="CustomerName">#Html.DisplayFor(model=>model.CustomerName)</span>
Ugly, but works ;-) (required field, without rendering .EditorFor content get lost during submit, even HTML comment around does not work, tested on System.Web.Mvc 5.0.0.0)
<b style="display:none">#Html.EditorFor(model => model.UserName)</b>
<input name="UserName" disabled readonly value=#Html.DisplayTextFor(model => model.UserName)>
Original looked like:
<input class="text-box single-line" data-val="true" data-val-required="The User Name field is required." id="UserName" name="UserName" type="text" value="Hate Razor !">
You use the below
<span title="Customer name">#Html.DisplayTextFor(m => m.CustomerName)</span>

Resources