DateTime field and Html.TextBoxFor() helper. How to use it correctly?
Asked Answered
D

6

22

I have a DateTime field in my Model. If I try to use this field in a strong typed partial view this way

<%= Html.TextBoxFor(model => model.DataUdienza.ToString("dd/MM/yyyy"), new { style = "width: 120px" })  %>

I will get the following compilation error at runtime

System.InvalidOperationException : Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

Anyway if I use it removing the formatting, ToString("dd/MM/yyyy"), everything works but the field is formatted using the time part which I dont need at all.

Where I am doing wrong? Which is the correct way to handle this?

thanks for helping!

EDIT

This is the property declaration in the model class

[Required]
[DisplayName("Data Udienza")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime DataUdienza { get; set; }
Damal answered 17/9, 2010 at 11:19 Comment(0)
B
12

Create an editor template called DateTime.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
<%=Html.TextBox("", (Model.HasValue ? Model.Value.ToString("MM/dd/yyyy") : string.Empty), ViewData) %>

Put it in your Views/Shared/EditorTemplates folder. Now when you call:

<%= Html.EditorFor(model => model.DataUdienza) %>

Your DateTime will be formatted without the time.

This will happen with all DateTimes called this way, though...

Custom html attributes can be used in this way:

<%= Html.EditorFor(model => model.DataUdienza, new {customAttr = "custom", @class = "class"}) %>

It passes through to the EditorTemplate as ViewData.

Bustard answered 17/9, 2010 at 13:40 Comment(0)
E
24

i use this in mvc 4. it also works~

@Html.TextBoxFor(x => x.DatePurchase, "{0:yyyy-MM-dd}", new { @class = "dateInput", @placeholder = "plz input date" })
Ephesus answered 8/6, 2012 at 3:15 Comment(1)
Thanks very nice solution. but i really need to see why it has not used the culture info of the settings specified in the web config.Numbskull
P
19
<%= Html.EditorFor(model => model.DataUdienza) %>

And in your model:

[DisplayFormat(ApplyFormatInEditMode = true, 
               DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime DataUdienza { get; set; }

The drawback with EditorFor is that you cannot apply custom html attributes to the generated field. As an alternative you could use the TextBox helper:

<%= Html.TextBox("DataUdienza", Model.Date.ToString("dd/MM/yyyy"), new { style = "width: 120px" })%>
Pneumatograph answered 17/9, 2010 at 11:22 Comment(6)
Wow! Superfast. Thank you :) I'm gonna try it. But, in the meanwhile, how does this work if the field is a Nullable type?Damal
Works the same for nullable types.Pneumatograph
I have tried to apply your solution but unfortunately does'nt work. I am gonna edit the post to add the model property declaration for your information.Damal
@Lorenzo, did you notice that Html.EditorFor should be used instead of Html.TextBoxFor?Pneumatograph
@Darin: I have never used the EditorFor before. Anyway please consider that the two attributes (DataType and DisplayFormat) have been added now for trying your suggestion.Damal
Thanks for this, I'm using the textbox helper because I needed the field to be readonly so I must pass in new {@readonly="readonly"} ThanksAlehouse
B
12

Create an editor template called DateTime.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
<%=Html.TextBox("", (Model.HasValue ? Model.Value.ToString("MM/dd/yyyy") : string.Empty), ViewData) %>

Put it in your Views/Shared/EditorTemplates folder. Now when you call:

<%= Html.EditorFor(model => model.DataUdienza) %>

Your DateTime will be formatted without the time.

This will happen with all DateTimes called this way, though...

Custom html attributes can be used in this way:

<%= Html.EditorFor(model => model.DataUdienza, new {customAttr = "custom", @class = "class"}) %>

It passes through to the EditorTemplate as ViewData.

Bustard answered 17/9, 2010 at 13:40 Comment(0)
U
2

At least if using razor, you can name the template, so you don't need to use the same template for all DateTimes:

@Html.EditorFor(m => m.StartDate, "Date")

where Date.cshtml contains a TextBoxFor or some other editor, like @JungleFreak had explained:

@model DateTime?

@Html.TextBox("", Model.HasValue ? Model.Value.ToShortDateString() : string.Empty, 
    new { data_datepicker = true })
Unvarnished answered 25/7, 2012 at 20:9 Comment(0)
G
1

Perhaps an extension method could be created:

    public static MvcHtmlString DateTimeFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        var compilationResult = expression.Compile();
        TValue dateValue = compilationResult((TModel)html.ViewDataContainer.ViewData.Model);
        var body = (MemberExpression)expression.Body;
        return html.TextBox(body.Member.Name, (Convert.ToDateTime(dateValue)).ToCustomDateFormat(), new { id = body.Member.Name, datepicker = true });
    }

the method ToCustomDateFormat could be an extension method for dateTime types which returns string value in desired format.

Usage:

@Html.DateTimeFor(x=>x.AnyDateTimeProperty)

Worked fine for me (for DateTime and DateTime? properties), although I am not sure if compiling the expression on run-time is a good idea.

Geisha answered 10/9, 2013 at 19:35 Comment(0)
G
0

just add

@type = 'datetime-local'

For Example

@Html.TextBoxFor(x => x.DatePurchase, new { @class = "dateInput", @placeholder = "plz input date", @type = "datetime-local" })
Grandpa answered 23/6, 2023 at 6:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.