2

I am using ASP.NET MVC2 with MvcContrib.FluentHtml to do form binding.

I want to bind a DateTime format to a textbox with specific datetime format.

<%=this.TextBox(c => c.date_a).Class("readonly text-box") %>
// PS. c.date_a is a DateTime

gives me

<input type="text" value="5/9/2009 12:00:00 AM" name="date_a" id="datea" class="readonly text-box">

However, I'd like to override the default datetime format. e.g.

value="2009-5-9" 
value="9-5-09" 
value="09May9" 

I know I can override the value by specific a value, however, the date should also bind to the object class on POST the form.

How to do "minimum" code to override the default datetime format of a specific field on UI?

skaffman
  • 398,947
  • 96
  • 818
  • 769
Dennis C
  • 24,511
  • 12
  • 71
  • 99

5 Answers5

9

I don't know if this work with MvcContrib MvcContrib.FluentHtml but without it, it is very simple, add to your model property

[DisplayFormat(DataFormatString="{0:MM/dd/yyyy}", ApplyFormatInEditMode=true)]

and in your view

m.DateProperty) %>

I Don't know if MvcContrib uses Attributes but if it doesn't, it should, that way, you'll always have your date the same format, specifying the format only once...

hope this help

moi_meme
  • 9,180
  • 4
  • 44
  • 63
  • As far as i know - it does not. – Arnis Lapsa Feb 10 '10 at 22:07
  • I would go with this approach unless you mean domain model (instead of view model). – Arnis Lapsa Feb 10 '10 at 22:11
  • It looks clean and good, however, I am using LINQ2SQL that is difficult to add DisplayFormatAttribute to property in generated code. – Dennis C Feb 11 '10 at 01:27
  • You can simply define a validator class check http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx for an example – moi_meme Feb 11 '10 at 02:38
  • Thanks, I had this same problem. Any reason why [DisplayFormat] doesn't work with TextBoxFor()? – Lucas Mar 30 '10 at 22:28
  • I'm not sure but the EditorHelper calls the TextBoxHelper sending it the formated value... and the textBoxHelper doesn't even check for that. – moi_meme Mar 31 '10 at 01:01
  • 4
    The problem with using an attribute in this way is that you're bolting a view concern onto the data object. What if I want "3/8/10" when showing in a grid, but "March 8, 2010" in the detail? A common scenario. Do the formatting in the view, where that concern belongs. – Tim Scott Aug 05 '10 at 15:18
  • The source of the problem is from HTML. There is no date field until HTML5. These are same text users read, and browsers submit to server. – Dennis C Mar 09 '11 at 08:13
1

First, add this extension for getting property path:

public static string GetPropertyPath<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> property)
{                       
     Match match = Regex.Match(property.ToString(), @"^[^\.]+\.([^\(\)]+)$");
     return match.Groups[1].Value;
}

Than add this extensions for HtmlHalper:

public static MvcHtmlString DateBoxFor<TEntity>(
            this HtmlHelper helper,
            TEntity model,
            Expression<Func<TEntity, DateTime?>> property,
            object htmlAttributes)
        {
            DateTime? date = property.Compile().Invoke(model);
            var value = date.HasValue ? date.Value.ToShortDateString() : string.Empty;
            var name = ExpressionParseHelper.GetPropertyPath(property);

            return helper.TextBox(name, value, htmlAttributes);
        }

Also you should add this jQuery code:

$(function() {
    $("input.datebox").datepicker();
});

datepicker is a jQuery plugin.

And now you can use it:

 <%= Html.DateBoxFor(Model, (x => x.Entity.SomeDate), new { @class = "datebox" }) %>
Serhiy
  • 4,357
  • 5
  • 37
  • 53
1

I often run into situations where it's impractical to modify the model (with attributes etc) so being able to implement a solution like Сергій's is important. To Dennis Cheung point though, you can more tightly bind this solution as follows:

public static MvcHtmlString DateBoxFor<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, DateTime?>> property)
{
    return helper.DateBoxFor(property, "d", null);
}

public static MvcHtmlString DateBoxFor<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, DateTime?>> property, string format, object htmlAttributes)
{
    var viewData = helper.ViewContext.ViewData;
    var date = property.Compile().Invoke(viewData.Model);
    var value = date.HasValue ? date.Value.ToString(format) : string.Empty;
    var name = viewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(property));

    return helper.TextBox(name, value, htmlAttributes);
}

Then you call it like this:

<%:Html.DateBoxFor(m => m.SomeDate)%>

Or like this:

<%:Html.DateBoxFor(m => m.SomeDate, "d", null)%>
0

I am not sure whether this would cause you problems when the value is posted back but the following syntax should allow you to change the format with which the date value is displayed.

<%=this.TextBox(c => c.date_a.ToString('yyyy-M-d')).Class("readonly text-box") %>

You will find further information on how to construct the format strings here.

Scott Munro
  • 13,369
  • 3
  • 74
  • 80
0

With FluentHtml you can do like this:

<%=this.TextBox(c => c.date_a).Class("readonly text-box").Format("yyyy-M-d") %>
Tim Scott
  • 15,106
  • 9
  • 65
  • 79