Custom EditorFor Template and htmlAttributes - asp.net-mvc

I'm trying to use EditorFor custom templates.
I want to create a Int32 and decimal templates to render the inputs with some validations.
This is what I'm trying
#model int?
#Html.TextBoxFor(model => model, null, new { #type="text", #oninput = "this.value=this.value.replace(/[^0-9]/g,'')" } )
And I call it like
#Html.EditorFor(x => x.ExampleIntField)
It renders an <input type="text", oninput="this.value=this.value.replace(/[^0-9]/g,'')"
To here everything works, but when I try to pass extra htmlAttributes like readonly I don't understand how I must receive it in EditorFor template.
Example
#Html.EditorFor(x => x.ExampleIntField, new { htmlAttributes = new { #readonly = "readonly" } } )
I tried this I got the exact same <input type="text", oninput="this.value=this.value.replace(/[^0-9]/g,'')" rendered without readonly attribute

You are using the overload of EditorFor() that passes the object as additionalViewData. You can read that within the template from the ViewDataDictionary
#model int?
#{ var attributes = ViewData["htmlAttributes"]; } // returns { #readonly = "readonly" }
which you could then merge with your existing attributes and use in the TextBoxFor() method.
#{
var htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(attributes);
htmlAttributes.Add("oninput", "this.value=this.value.replace(/[^0-9]/g,'')";
}
#Html.TextBoxFor(model => model, htmlAttributes)
Note that TextBoxFor() generates type="text" so there is no need to add it again. In addition, you do not need the leading # unless its a reserved keyword (for example #class = "...")

Related

ASP.NET MVC 4 - Set input value using #Html.EditorFor

Currently i have this field on a form:
#Html.EditorFor(model => model.AmountDecimal,
new { htmlAttributes = new { #class = "form-control" } })
But:
a) i want it to have the value "100" predefined
b) don't want it to be editable
I know how to do it in raw HTML but i need it to be in razor.
Thanks
It would make sense to set this value e.g. in the constructor of your model or in the controller before you call your view
public ActionResult MyAction()
{
var model = new MyViewModel
{
AmountDecimal= 100
};
return View(model);
}
But if you really like to do it in razor, you may use HiddenFor
#Html.HiddenFor(model => model.AmountDecimal, new { #Value = "100" });
<input type="text" name = "dummy" class="form-control" value="100" readonly/>
Keep in mind to never trust a user input ;)
I think your are loooking for something like this:
#Html.EditorFor(model => model.AmountDecimal,
new { htmlAttributes = new { #class = "form-control", #Value = "100", #readonly = "readonly"} })

Razor syntax for DropDownListFor

How can I write code below with a HTML helper?
<select name="CountryId">
#foreach (var c in ViewBag.Counties) {
<option value="#c.Id">#c.Name</option>
}
</select>
This code above will give the right html code in my browser. But if I use the HTML helper below the value attribute from the option tags are missing.
#Html.DropDownListFor(
model => model.CountryId,
new SelectList(ViewBag.Countries, "Name"),
new { htmlAttributes = new { #class = "form-control" } }
)
What's wrong in this code if you know that ViewBag.Counties is an object from type List<Country> and has the properties Name (type of string) and CounrtyId (type of int).
Try this.your selectlist item class should be created in the parent class that is model class you are binding in the view page.
#Html.DropDownListFor(model => model.CountryId,new SelectList(ViewBag.Countries,"CountryID", "CountryName"),new {#class='form-control'})

Custom editor template for Enum - How to handle null in Create view?

I am trying to create a custom editor template for enum properties.
I thought I had it good. Rob Lyndon helped me with a htmlHelper extension and it worked great on the Edit view.
But on the Create view it errors out because the value is null.
If I make the model nullable Enum? then I won't be able to get the values to populate the select list.
I don't want to have to initialize all models with a default value. And I would like to avoid having to create a different editor template for each type of enum.
Are there any better alternatives?
HtmlHelper
public static MvcHtmlString EnumTextDropDownListFor<TModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, Enum>> expression, Type enumType, object htmlAttributes)
{
var enumValues = Enum.GetValues(enumType).OfType<Enum>().Select(v => v.ToString()).ToArray();
var selectList = new SelectList(enumValues.Select(v => new SelectListItem { Text = v, Value = v }));
return html.DropDownListFor(expression, selectList, htmlAttributes);
}
Editor Template
#model Enum
#{
var htmlAttributesFromView = ViewData["htmlAttributes"] ?? new { };
var htmlAttributes = Html.MergeHtmlAttributes(htmlAttributesFromView, new { #class = "form-control" });
var type = Model.GetType();
}
<div class="form-group">
#Html.LabelFor(model => model, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-8">
#Html.EnumTextDropDownListFor(model => model, type, htmlAttributes)
#Html.ValidationMessageFor(model => model)
</div>
<a class="infoonclick col-md-1" title="#Html.DisplayNameFor(model => model)" data-content="#Html.DescriptionFor(model => model)">
<span class="fa fa-info-circle"></span>
</a>
</div>
I use
#model Enum
#Html.EnumDropDownListFor(model => model, new { #class = "form-control" })
in my Enum.cshtml view
It might be a bit late, but I just came across this problem and this is how I solved it:
#{
var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType)
?? ViewData.ModelMetadata.ModelType;
}
This will allow the model to be null and avoid the nullref error you would otherwise get trying to query the type of the "null" model.
in latest dotnet core just use the following:
1- make the model dynamic
#model dynamic
2- get the enum type with:
var enumType = ViewData.ModelMetadata.UnderlyingOrModelType;
this will handle both nullable and non-nullable enums

MVC 5.1 - Adding Html attributes in EditorFor with customized Editor Templates

I can add htmlAttributes like following and its rendered in Html
#Html.EditorFor(Function(model) model.LastName, New With {Key .htmlAttributes = New With {Key .ng_model = "model.LastName"}})
But when I added a custom editor template for Date Data type in the Views\Shared\EditorTemplates\Date.vbhtml as follows
#Code
Dim value = ""
If Not Model Is Nothing Then
value = String.Format("{0:d}", Model.Value.ToString("dd/MM/yyyy"))
End If
#Html.TextBox("", value, New With {Key .class = "datefield", Key .type = "text"})
End Code
and I use the EditorFor with htmlAttributes then the HtmlAttributes are not rendering?
This is an example of code I am using for a custom DateTime editor template. I was able to access the htmlattributes being passed into editorfor. Hope this helps.
#model DateTime
#{
object htmlAttributes = null;
if (ViewContext.ViewData.Keys.Contains("htmlAttributes"))
{
htmlAttributes = ViewContext.ViewData["htmlAttributes"];
}
}
#Html.TextBoxFor(model => model, htmlAttributes)

How can I set id using Html.EditorFor with MVC3

I am trying to set a field id as follows:
#Html.EditorFor(x => x.Order, new { id = string.Format("Order_{0}", Model.Row) })
but this results in the following and it seems my id is not being set:
<input type="text" value="334" name="item.Order" id="item_Order" class="text-box single-line">
Does anyone have an idea what I am doing wrong. I checked the allowable formats for EditorFor and looked on google for examples but I could not see anything that matched what I need.
You should change to
#Html.TextBoxFor(x => x.Order, new { id = string.Format("Order_{0}", Model.Row) })
The second parameter of #Html.EditorFor is for view data, not for html attributes
#Html.EditorFor(x => x.Order, null, string.Format("Order_{0}", Model.Row))
I know this question is pretty old, but all I needed to do was the following:
#Html.EditorFor(modelItem => item.EndDate,
new { htmlAttributes = new { #class = "form-control", #id = #endID } })
You can give it whatever classes or id that you want/need. I have this earlier in my page as well to create a different ID for each item:
string endID = "end-" + #item.ID;
Hopefully this helps someone in the future.
have you tried creating an editor template for your x.Order?
have this on your editor template:
<input type="text" id="#ViewData["id"]">
and use this on your view page:
#Html.EditorFor(x => x.Order, new { id = string.Format("Order_{0}", Model.Row) })
I'm not sure if you can override the ID attribute when using the strongly typed helpers. But you can use the other non-model type:
#Html.Editor(string.Format("Order_{0}", Model.Row), Model.Order)
This will use the first parameter as the ID and the second as the default value.
If you want to use EditorFor, you can do this:
#Html.EditorFor(model => model.Order, new { htmlAttributes = new { #id = "YOUR_ID_HERE"})
For the above example it would be:
#Html.EditorFor(model => model.Order, new { htmlAttributes = new { #id = $"Order_{0}" } })
Svetlosav's answer looks good but it will mess up your data binding. If you use that answer, check to see if your model is populating as expected and not with a default value (null, false, 0, etc..).

Resources