MVC4 DataType.Date EditorFor จะไม่แสดงค่าวันที่ใน Chrome, ดีใน Internet Explorer


198

ฉันกำลังใช้แอตทริบิวต์ DataType.Date กับรุ่นของฉันและ EditorFor ในมุมมองของฉัน สิ่งนี้ทำงานได้ดีในInternet Explorer 8และInternet Explorer 9แต่ในGoogle Chromeจะแสดงตัวใช้เลือกวันที่และแทนที่จะแสดงค่าเพียงแสดง "เดือน / วัน / ปี" ในข้อความสีเทาจาง

ทำไม Google Chrome ถึงไม่แสดงค่า?

รุ่น:

[DataType(DataType.Date)]
public Nullable<System.DateTime> EstPurchaseDate { get; set; }

ดู:

<td class="fieldLabel">Est. Pur. Date</td>
<td class="field">@Html.EditorFor(m=>m.EstPurchaseDate)</td>

โครเมียม

Internet Explorer

คำตอบ:


377

เมื่อคุณตกแต่งคุณสมบัติของโมเดลด้วย[DataType(DataType.Date)]เทมเพลตเริ่มต้นใน ASP.NET MVC 4 จะสร้างฟิลด์อินพุตเป็นtype="date":

<input class="text-box single-line" 
       data-val="true" 
       data-val-date="The field EstPurchaseDate must be a date."
       id="EstPurchaseDate" 
       name="EstPurchaseDate" 
       type="date" value="9/28/2012" />

เบราว์เซอร์ที่รองรับ HTML5 เช่น Google Chrome แสดงช่องป้อนข้อมูลนี้ด้วยตัวใช้เลือกวันที่

2012-09-28เพื่อที่จะแสดงวันที่อย่างถูกต้องคุ้มค่าที่จะต้องจัดรูปแบบเป็น อ้างจากสเปค :

ค่า:วันที่ที่ถูกต้องตามที่กำหนดใน [RFC 3339] ที่มีคุณสมบัติเพิ่มเติมว่าองค์ประกอบปีเป็นตัวเลขสี่หลักขึ้นไปซึ่งเป็นตัวเลขที่มากกว่า 0

คุณสามารถบังคับใช้รูปแบบนี้โดยใช้DisplayFormatแอตทริบิวต์:

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public Nullable<System.DateTime> EstPurchaseDate { get; set; }

44
ดารินขอขอบคุณที่สมบูรณ์แบบ! คุณได้ตอบคำถาม MVC ของฉันมากมายในช่วงสองปีที่ผ่านมา
Ben Finkel

3
คำตอบที่ยอดเยี่ยม แต่ฉันรู้สึกว่านี่เป็นเรื่องน่าสนใจที่คุณต้องบังคับมันเพื่อให้การควบคุมทำงานได้อย่างถูกต้อง!
Coops

7
สิ่งที่จะเป็นวิธีการทำ "ทั่วโลก" สำหรับคุณสมบัติทั้งหมดที่ทำเครื่องหมาย[DataType(DataType.Date)]ดังนั้นฉันไม่ต้องทำเครื่องหมายคุณสมบัติทั้งหมดเหล่านี้แยกจากกันด้วยความเสี่ยงที่จะหายไปบางส่วน
Marjan Venema

7
ดารินทร์, คนที่อยู่นอกสหรัฐอเมริกาสามารถทำอะไรได้บ้าง? ฉันจะตั้งค่าข้อมูลจำเพาะ แต่แสดงรูปแบบวันที่ที่กำหนดเองได้อย่างไร เช่นสหราชอาณาจักร
Piotr Kula

3
@ MarjanVenema- ฉันใช้ "ExtensibleModelMetadataProvider" จาก FailTracker ของ Matt Honeycutt ( github.com/MattHoneycutt/Fail-Tracker ) ดูภายใต้โฟลเดอร์โครงสร้างพื้นฐานเพื่อ ModelMetadata ฉันใช้คลาสเหล่านั้นแล้วสร้างการใช้งานตัวกรองของ IModelMetadataFilter เมื่อมีการเรียกเมธอด TransformMetadata คุณสามารถแก้ไขคุณสมบัติ "DisplayFormatString" และ "EditFormatString" ของข้อมูลเมตาได้ หวังว่าสิ่งนี้จะทำให้คุณไปในทิศทางที่ถูกต้อง (btw มีวิดีโอ pluralsight ที่ยอดเยี่ยมที่ใช้ Fail-Tracker)
SwampyFox

44

ใน MVC5.2 เพิ่ม Date.cshtml ไปยังโฟลเดอร์ ~ / Views / Shared / EditorTemplates:

@model DateTime?
@{
    IDictionary<string, object> htmlAttributes;
    object objAttributes;
    if (ViewData.TryGetValue("htmlAttributes", out objAttributes))
    {
        htmlAttributes = objAttributes as IDictionary<string, object> ?? HtmlHelper.AnonymousObjectToHtmlAttributes(objAttributes);
    }
    else
    {
        htmlAttributes = new RouteValueDictionary();
    }
    htmlAttributes.Add("type", "date");
    String format = (Request.UserAgent != null && Request.UserAgent.Contains("Chrome")) ? "{0:yyyy-MM-dd}" : "{0:d}";
    @Html.TextBox("", Model, format, htmlAttributes)
}

ขอบคุณ! แก้ไข "ปัญหา" ของโครเมี่ยมที่กล่าวถึงและแน่นอนว่าคุณสามารถมีรูปแบบการแสดงผลอื่นในคุณสมบัติ datetime ของคุณ!
cmxl

ใช่ทางออกที่ดี นี่เป็นการทำงานที่ยอดเยี่ยมสำหรับพวกเราที่ไม่ได้อยู่ในสหรัฐอเมริกา
Richard McKenna

ฉันคิดว่านี่เป็นวิธีแก้ปัญหาที่ดีที่สุดแก้ไขได้เพียงแค่แก้ไขปัญหาและไม่มีผลต่อการจัดรูปแบบการแสดงผลที่มีอยู่
dsghi

1
การใช้ "Date.cshtml" แทนที่จะเป็น "DateTime.cshtml" เป็นคำตอบที่มหัศจรรย์! มันใช้งานได้ใน MVC 4 เช่นกัน
Atron Seige

ที่ดี! Obrigado
Guilherme de Jesus Santos

16

นอกเหนือจากคำตอบของดารินดิมิทรอฟ:

หากคุณต้องการให้บรรทัดนี้เฉพาะใช้รูปแบบบางอย่าง (แตกต่างจากมาตรฐาน) คุณสามารถใช้ใน MVC5:

@Html.EditorFor(model => model.Property, new {htmlAttributes = new {@Value = @Model.Property.ToString("yyyy-MM-dd"), @class = "customclass" } })

เนื่องจากมี@จุดเริ่มต้นที่@Value = @Model.Property...ยังคงต้องการที่@? คุณหมายถึงเพียงแค่new { Value = Model.Property...?
user3454439

11

ใน MVC 3 ฉันต้องเพิ่ม:

using System.ComponentModel.DataAnnotations;

ระหว่างการใช้เมื่อเพิ่มคุณสมบัติ:

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

โดยเฉพาะถ้าคุณกำลังเพิ่มคุณสมบัติเหล่านี้ในไฟล์. edmx อย่างฉัน ฉันพบว่าโดยค่าเริ่มต้น. edmx ไฟล์ไม่ได้ใช้สิ่งนี้ดังนั้นการเพิ่มเพียงอย่างเดียวไม่เพียงพอ


10

หากคุณลบออก[DataType(DataType.Date)]จากแบบจำลองของคุณช่องป้อนข้อมูลใน Chrome จะแสดงผลเป็นtype="datetime"และจะไม่แสดง datepicker เช่นกัน


ขอบคุณเบอร์นี ฉันไม่ได้มีปัญหากับตัวเลือกที่ปรากฏขึ้นเนื่องจากฉันไม่ได้ใส่ข้อมูลลงในกล่องป้อนข้อมูล นี่เป็นการดีที่จะรู้
Ben Finkel

โอเปร่าแสดงผล datepicker ว่า ใช้ modernizr เพื่อทำ polyfill
cleftheris

1
dateถ้ามันควรจะเป็นวันที่มันควรจะกลายเป็นเข้าของพิมพ์ การใช้datetimeงานเป็นวิธีการแก้ไขที่ไม่เหมาะสมเนื่องจากมันไม่ได้เป็นตัวแทนของข้อมูล
Chris Pratt

4

ฉันยังคงมีปัญหากับมันผ่านรูปแบบ yyyy-MM-dd แต่ฉันได้รับมันโดยการเปลี่ยน Date.cshtml:

@model DateTime?

@{
    string date = string.Empty;
    if (Model != null)
    {
        date = string.Format("{0}-{1}-{2}", Model.Value.Year, Model.Value.Month, Model.Value.Day);
    }

    @Html.TextBox(string.Empty, date, new { @class = "datefield", type = "date"  })
}

ขอบคุณในที่สุดก็ใช้งานได้ฉันพยายามที่string.Format("{0}/{1}/{2}")จะได้รับdd/mm/yyyyรูปแบบและใช้งานได้ดีฉันใช้ฐานข้อมูลวิธีแรก แต่ DisplayFormat ไม่ได้ทำงานกับชั้นเรียนบางส่วนไม่ทราบว่าทำไม? อย่างไรก็ตามใครก็ตามถ้าต้องการลองวิธีนี้
อย่า

3

ตอบกลับMVC4 DataType วันที่ EditorFor จะไม่แสดงค่าวันที่ใน Chrome ปรับใน IE

ในรุ่นคุณจะต้องมีประเภทของการประกาศดังต่อไปนี้:

[DataType(DataType.Date)]
public DateTime? DateXYZ { get; set; }

หรือ

[DataType(DataType.Date)]
public Nullable<System.DateTime> DateXYZ { get; set; }

คุณไม่จำเป็นต้องใช้แอตทริบิวต์ต่อไปนี้:

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

ที่ Date.cshtml ใช้เทมเพลตนี้:

@model Nullable<DateTime>
@using System.Globalization;

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

    }

    if (Request.Browser.Type.ToUpper().Contains("IE") || Request.Browser.Type.Contains("InternetExplorer"))
    {
        @Html.TextBox("", String.Format("{0:d}", dt.ToShortDateString()), new { @class = "datefield", type = "date" })
    }
    else
    {
        //Tested in chrome
        DateTimeFormatInfo dtfi = CultureInfo.CreateSpecificCulture("en-US").DateTimeFormat;
        dtfi.DateSeparator = "-";
        dtfi.ShortDatePattern = @"yyyy/MM/dd"; 
        @Html.TextBox("", String.Format("{0:d}", dt.ToString("d", dtfi)), new { @class = "datefield", type = "date" })
    } 
}

มีความสุข! ขอแสดงความนับถือ Blerton


หากคุณทำเช่นนี้ Chrome จะไม่ให้เครื่องมือเลือกวันที่ให้คุณ ฉันใช้โซลูชันของคุณ แต่แก้ไขเพื่อให้ 1) ฉันใช้DisplayFormatคุณลักษณะ 2) เปลี่ยนการทดสอบเพื่อตรวจสอบว่าประเภทของเบราว์เซอร์เป็นโครมหรือไม่แล้วทำ@Html.EditorFor(m=>m.EstPurchaseDate)3) ทำอย่างอื่น@Html.TextBox("EstPurchaseDate", dt.ToString("MM/dd/yyyy"))หมายเหตุ: ใน # 2 การตรวจสอบที่ดีกว่าจะเป็นอย่างไร เบราว์เซอร์เข้าใจ HTML5 แต่ฉันไม่รู้ว่าต้องทำอย่างไร
David

4
Downvoting สำหรับตรวจจับเบราว์เซอร์ในรหัสฝั่งเซิร์ฟเวอร์
Tetsujin no Oni

1

หากคุณต้องการควบคุมรูปแบบของวันที่ (กล่าวคือไม่ใช่รูปแบบ yyyy-mm-dd เป็นที่ยอมรับ) โซลูชันอื่นอาจเพิ่มคุณสมบัติตัวช่วยที่เป็นสตริงชนิดและเพิ่มตัวตรวจสอบวันที่ไปยังคุณสมบัตินั้น และเชื่อมโยงกับคุณสมบัตินี้บน UI

    [Display(Name = "Due date")]
    [Required]
    [AllowHtml]
    [DateValidation]
    public string DueDateString { get; set; }

    public DateTime? DueDate 
    {
        get
        {
            return string.IsNullOrEmpty(DueDateString) ? (DateTime?)null : DateTime.Parse(DueDateString);
        }
        set
        {
            DueDateString = value == null ? null : value.Value.ToString("d");
        }
    }

และนี่คือตัวตรวจสอบวันที่:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class DateValidationAttribute : ValidationAttribute
{
    public DateValidationAttribute()
    {
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            DateTime date;

            if (value is string)
            {
                if (!DateTime.TryParse((string)value, out date))
                {
                    return new ValidationResult(validationContext.DisplayName + " must be a valid date.");
                }
            }
            else
                date = (DateTime)value;

            if (date < new DateTime(1900, 1, 1) || date > new DateTime(3000, 12, 31))
            {
                return new ValidationResult(validationContext.DisplayName + " must be a valid date.");
            }
        }
        return null;
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.