7

I am trying to get the Bootstrap Datepicker to work. I followed instructions from these sources:

How to add Date Picker Bootstrap 3 on MVC 5 project using the Razor engine? (Answer bei Enzero)

&

http://bootstrap-datepicker.readthedocs.org/en/latest/options.html#format

The problem is, that instead of the common american mm/dd/yyyy format, I want to use the german format (dd.mm.yyyy). So I did the following:

In Model:

[Required]
[DataType(DataType.Date)]
[Display(Name = "Datum")]
[DisplayFormat(DataFormatString = "{0:dd.MM.yyyy}", ApplyFormatInEditMode = true)]
public DateTime? Day { get; set; }

In Web.Config:

<system.web>
<globalization culture="de-DE" uiCulture="de-DE" />
...
</system.web>

In Scripts\DatePickerReady.js:

if (!Modernizr.inputtypes.date) {
    $(function () {
        var date = new Date();
        date.setDate(date.getDate());
        $(".datecontrol").datepicker({
            startDate: date,
            format: 'dd.mm.yyyy'
        });
    });
}

The result is this:

Which is essentially what I want. The problem is now that validation says that the date format is wrong. "The field Datum must be date" enter image description here

So the question is, why is validation not accepting the date?

EDIT #1:

I also use an EditorTemplate for date: (Views/Shared/EditorTemplates/date.cshtml):

@model Nullable<DateTime>

@{
    DateTime dt = DateTime.Now;

    if (Model != null)
    {
        dt = (System.DateTime) Model;
    }

    @Html.TextBox("", String.Format("{0:d}", dt.ToShortDateString()), new { @class = "form-control datecontrol", type = "date" })
}

EDIT #2: I just read that DisplayFormat is not recognized when you use a TextBox (instead of e.g. an EditorFor). That explains why Validation is not working. But I still don't know how to solve it, yet.

EDIT #3:

This is the HTML code for the Date field that I get I see in IE F12:

<input name="Day" class="form-control datecontrol input-validation-error" id="Day" aria-invalid="true" aria-required="true" aria-describedby="Day-error" type="date" value="11.08.2015" data-val-required="The Datum field is required." data-val="true" data-val-date="The field Datum must be a date.">

The scripts that are loaded on the page are: jquery-2.1.4.js, bootstrap.js, bootstrap-datepicker.js, DatePickerReady.js, respond.js, jquery.validate.js, jquery.validate.unobtrusive.js

EDIT #4: I now use this in DatePickerReady.js:

if (!Modernizr.inputtypes.date) {
    $(function () {
        var date = new Date();
        date.setDate(date.getDate());
        $(".datecontrol").datepicker({
            startDate: date,
            format: 'dd.mm.yyyy',
            autoclose: true,
            todayHighlight: true,
            weekStart: 1,
            language: 'de-DE',
            calendarWeeks: true
        });
    });
}

Every attribute works, but the 'de-DE' does not seem to do a thing. Language of the days is still in english. The validation issue also persists.

Further information: ASP.NET MVC 5, .NET 4.6, Bootstrap.Datepicker 1.4.0, jQuery 2.1.4, jQuery.Validation 1.14.0, Microsoft.jQuery.Unobtrusive.Validation 3.2.3

Community
  • 1
  • 1
  • Are you sure this doesn't have anything to do with the validation in any of your javascripts? Have a look at this: [link](http://stackoverflow.com/questions/18546971/mvc-4-how-to-validate-a-non-us-date-with-client-validation) – Johan Brännmar Aug 11 '15 at 14:41
  • 1
    Please check if this is a clientside error or server error with network tab in f12 tools – Mathias F Aug 11 '15 at 14:42
  • @branmar I checked the link and tried implementing it. Although I loaded all scripts mentioned, I get errors. I can't get that to work. –  Aug 12 '15 at 08:48
  • @MalcolmFrexner The network tab in F12 says nothing about any error when I play with the datepicker. –  Aug 12 '15 at 08:54

4 Answers4

3

I had a similar problem when I wanted to use "dd MMM yyyy" as a date format and found the solution was to write my own jQuery validator code.

$(function () {
    try {
        $.validator.addMethod('date',
        function (value, element) {
            if (this.optional(element)) {
                return true;
            }
            var ok = true;
            try {
                ok = moment(value, "dd.mm.yyyy", true).isValid();   
            } catch (err) {
                ok = false;
            }
            return ok;
        });
    } catch (e) { }
});

Note - This uses moment.js for the validation, but as this is needed by the bootstrap datetimepicker then this shouldn't be a problem. Change the format to match your requirements.

Update - apologies, just realised there was a bug in the original code I uploaded. I've edited it and it should work now

Jon Clarke
  • 366
  • 2
  • 14
  • And how do you implement that on the page? do you omit jqueryval? –  Sep 16 '15 at 15:06
  • I just have it in my view page within a scripts section so that it gets rendered into the output page. I'm not using the jqueryval bundle in my code so you should be ok to omit it. – Jon Clarke Sep 17 '15 at 10:21
2

My configuration: Model:

[Required]
[Display(ResourceType = typeof(Resources.Data), Name = "FerretBirthDay")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd'/'MM'/'yyyy}")]
[DataType(DataType.Date)]
public DateTime BirthDate { get; set; }

View:

@Html.TextBoxFor(m => m.BirthDate, "{0:dd.MM.yyyy}", new { @class = "form-control", id = "birthDate" })

$("#birthDate").datepicker();

I have ru-RU culture, but in format of date it's equal to de-DE. Suddenly, it works.

Backs
  • 24,430
  • 5
  • 58
  • 85
  • thank you for your answer, but I just read that the DisplayFormat isn't used at all when you use a TextBox. See my updated post for the EditorTemplate I use. This could explain why the validation with the DisplayFormat is not working. I also just tried your solution, without success. That's logical if TextBox does not care for DisplayFormat. –  Aug 11 '15 at 15:10
  • @zuckerthoben yes, i forgot about this, you need to use EditorFor. So, my solution is not to use datepicker from jQuery, use EditorFor and display format i posted – Backs Aug 11 '15 at 15:28
  • Then I will always use HTML5 datepicker, right? Then IE users can't use it. Thats the reason I want to use the bootstrap datepicker. It also looks nice. –  Aug 12 '15 at 06:39
  • @zuckerthoben yes, yes, you are right. I really forgot about this, I'll explore my project today evening, and try to find answer – Backs Aug 12 '15 at 07:49
  • Thank you for your engagement. @Backs –  Aug 12 '15 at 08:18
  • @zuckerthoben did you my variant? – Backs Aug 17 '15 at 08:12
0

I had similar problem once. I had to change my UI culture (in web.config) and then it started validating properly. So try something like this:

<configuration>
<system.web>
    <globalization uiCulture="de-DE" culture="de-DE" />
</system.web>

Datepicker side:

$('.datepicker').datepicker({
   language: "de-DE"
});
stann1
  • 576
  • 3
  • 11
  • thats what I've written in the post. For better reading I cut everything unnecessary. –  Aug 11 '15 at 15:08
  • Sorry, I missed it. Did you also try setting the language on the datepicker itself (see my edit) – stann1 Aug 12 '15 at 07:35
  • I also tried that. The datepicker itself is returning the correct format, it's just a validation issue it seems. See my update for my current datepicker code. –  Aug 12 '15 at 07:45
  • The last thing I can think of: look at your editor template, in the textbox value you seem to override the display format that you set in the model. Try changing: String.Format("{0:d}", dt.ToShortDateString()) to this: dt.ToString(CultureInfo.GetCultureInfo("de-DE")) – stann1 Aug 12 '15 at 08:07
  • the format that the datepicker delivers is already accurate. Instead of CultureInfo.GetCultureInfo I just tried dt.ToString("dd.MM.yyyy"), because I dont want the time behind the date. With that the datepicker delivers the correct format, but he also did that pre-change. It's just the validation of the datepicker output. I would turn off validation for that field, if I knew how, because the datepicker will always deliver a correctly formatted date and if not I can always throw an error after the POST from the controller. –  Aug 12 '15 at 08:28
0

Here is my scenario:

BundleConfig.cs:

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                       "~/Scripts/jquery-{version}.js",
                       "~/Scripts/globalize.js",
                       "~/Scripts/globalize.culture.uk-UA.js"));

bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                      "~/Scripts/bootstrap.js",
                      "~/Scripts/bootstrap-datepicker.js",
                      "~/Scripts/bootstrap-datepicker.uk.js",
                      "~/Scripts/respond.js"));

bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/datepicker.css",
                      ));

Model:

[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
public DateTime? PaymentDate { get; set; }

View:

<div class="input-group date">
    @Html.EditorFor(model => model.PaymentDate, new
    {
        htmlAttributes = new
        {
            @class = "form-control form-date",
        }
     )
     <span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span>
</div>

Js:

<script>
    (function($, Globalize) {

        // Clone original methods we want to call into
        var originalMethods = {
            min: $.validator.methods.min,
            max: $.validator.methods.max,
            range: $.validator.methods.range
        };

        // Tell the validator that we want numbers parsed using Globalize

        $.validator.methods.number = function(value, element) {
            var val = Globalize.parseFloat(value);
            return this.optional(element) || ($.isNumeric(val));
        };

        // Tell the validator that we want dates parsed using Globalize

        $.validator.methods.date = function(value, element) {
            var val = Globalize.parseDate(value);
            return this.optional(element) || (val);
        };

        // Tell the validator that we want numbers parsed using Globalize,
        // then call into original implementation with parsed value

        $.validator.methods.min = function(value, element, param) {
            var val = Globalize.parseFloat(value);
            return originalMethods.min.call(this, val, element, param);
        };

        $.validator.methods.max = function(value, element, param) {
            var val = Globalize.parseFloat(value);
            return originalMethods.max.call(this, val, element, param);
        };

        $.validator.methods.range = function(value, element, param) {
            var val = Globalize.parseFloat(value);
            return originalMethods.range.call(this, val, element, param);
        };

    }(jQuery, Globalize));


    $().ready(function() {

        var currentCulture = '@Thread.CurrentThread.CurrentUICulture.ToString()';
        Globalize.culture(currentCulture);

        $('.form-date').datepicker({
            language: '@Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName',
            todayBtn: "linked"
        });

    });
</script>
sashaeve
  • 9,387
  • 10
  • 48
  • 61
  • Hi, thank you for your answer. I will look at this at a later date! –  Dec 15 '15 at 09:21