From bb07119b4ae3d5c8239187e0e4a50fd06d922440 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Thu, 9 Nov 2017 10:25:36 -0800 Subject: [PATCH] Handle "month" input type (#7022) Addresses #6615 --- src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs | 8 +++++++- .../Internal/DefaultEditorTemplates.cs | 8 ++++++++ .../ViewFeatures/TemplateRenderer.cs | 1 + .../InputTagHelperTest.cs | 6 ++++++ .../Internal/DefaultEditorTemplatesTest.cs | 8 ++++++++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs index 18407ace88..4e675e8d81 100644 --- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs +++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs @@ -36,6 +36,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers { "DateTime-local", "datetime-local" }, { nameof(DateTimeOffset), "text" }, { "Time", "time" }, + { "Month", "month" }, { nameof(Byte), "number" }, { nameof(SByte), "number" }, { nameof(Int16), "number" }, @@ -378,7 +379,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers private string GetFormat(ModelExplorer modelExplorer, string inputTypeHint, string inputType) { string format; - if (string.Equals("decimal", inputTypeHint, StringComparison.OrdinalIgnoreCase) && + if (string.Equals("month", inputType, StringComparison.OrdinalIgnoreCase)) + { + // A new HTML5 input type that only will be rendered in Rfc3339 mode + format = "{0:yyyy-MM}"; + } + else if (string.Equals("decimal", inputTypeHint, StringComparison.OrdinalIgnoreCase) && string.Equals("text", inputType, StringComparison.Ordinal) && string.IsNullOrEmpty(modelExplorer.Metadata.EditFormatString)) { diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/DefaultEditorTemplates.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/DefaultEditorTemplates.cs index 4db4c74011..38fe6db05f 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/DefaultEditorTemplates.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/DefaultEditorTemplates.cs @@ -370,6 +370,14 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal return GenerateTextBox(htmlHelper, inputType: "time"); } + public static IHtmlContent MonthInputTemplate(IHtmlHelper htmlHelper) + { + // A new HTML5 input type that only will be rendered in Rfc3339 mode + htmlHelper.Html5DateRenderingMode = Html5DateRenderingMode.Rfc3339; + ApplyRfc3339DateFormattingIfNeeded(htmlHelper, "{0:yyyy-MM}"); + return GenerateTextBox(htmlHelper, inputType: "month"); + } + public static IHtmlContent NumberInputTemplate(IHtmlHelper htmlHelper) { return GenerateTextBox(htmlHelper, inputType: "number"); diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/TemplateRenderer.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/TemplateRenderer.cs index 9ccc1cd361..666129ccf5 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/TemplateRenderer.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/TemplateRenderer.cs @@ -52,6 +52,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal { "DateTime-local", DefaultEditorTemplates.DateTimeLocalInputTemplate }, { nameof(DateTimeOffset), DefaultEditorTemplates.DateTimeOffsetTemplate }, { "Time", DefaultEditorTemplates.TimeInputTemplate }, + { "Month", DefaultEditorTemplates.MonthInputTemplate }, { typeof(byte).Name, DefaultEditorTemplates.NumberInputTemplate }, { typeof(sbyte).Name, DefaultEditorTemplates.NumberInputTemplate }, { typeof(short).Name, DefaultEditorTemplates.NumberInputTemplate }, diff --git a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/InputTagHelperTest.cs b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/InputTagHelperTest.cs index 987623ac57..efa0097ad1 100644 --- a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/InputTagHelperTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/InputTagHelperTest.cs @@ -1052,6 +1052,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers { "text", null, "text" }, { "TEXT", null, "text" }, { "time", null, "time" }, + { "month", "{0:yyyy-MM}", "month" }, { "UInt16", null, "number" }, { "uint16", null, "number" }, { "UInt32", null, "number" }, @@ -1217,6 +1218,8 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers [InlineData("DateTimeLocal", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fff}", "datetime-local")] [InlineData("Time", Html5DateRenderingMode.CurrentCulture, "{0:t}", "time")] // Format from [DataType]. [InlineData("Time", Html5DateRenderingMode.Rfc3339, "{0:HH:mm:ss.fff}", "time")] + [InlineData("Month", Html5DateRenderingMode.CurrentCulture, "{0:yyyy-MM}", "month")] + [InlineData("Month", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM}", "month")] [InlineData("NullableDate", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-dd}", "date")] [InlineData("NullableDateTime", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fff}", "datetime-local")] [InlineData("NullableDateTimeOffset", Html5DateRenderingMode.Rfc3339, "{0:yyyy-MM-ddTHH:mm:ss.fffK}", "text")] @@ -1377,6 +1380,9 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers [DataType(DataType.Time)] public DateTimeOffset Time { get; set; } + + [DataType("month")] + public DateTimeOffset Month { get; set; } } private class NestedModel diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Internal/DefaultEditorTemplatesTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Internal/DefaultEditorTemplatesTest.cs index 035f12de3e..1c0a100706 100644 --- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Internal/DefaultEditorTemplatesTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Internal/DefaultEditorTemplatesTest.cs @@ -57,6 +57,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal { "DateTimeOffset", "__TextBox__ class='text-box single-line' type='text'" }, { "Time", "__TextBox__ class='text-box single-line' type='time'" }, { "time", "__TextBox__ class='text-box single-line' type='time'" }, + { "Month", "__TextBox__ class='text-box single-line' type='month'" }, + { "month", "__TextBox__ class='text-box single-line' type='month'" }, { "Byte", "__TextBox__ class='text-box single-line' type='number'" }, { "BYTE", "__TextBox__ class='text-box single-line' type='number'" }, { "SByte", "__TextBox__ class='text-box single-line' type='number'" }, @@ -825,6 +827,7 @@ Environment.NewLine; [InlineData("datetime-local", null, "2000-01-02T03:04:05.060", "datetime-local")] [InlineData("DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.060-05:00", "text")] [InlineData("time", "{0:t}", "03:04:05.060", "time")] + [InlineData("month", "{0:yyyy-MM}", "2000-01", "month")] public void Editor_FindsCorrectDateOrTimeTemplate( string dataTypeName, string editFormatString, @@ -886,6 +889,7 @@ Environment.NewLine; [InlineData("datetime-local", null, "02/01/2000 03:04:05 -05:00", "datetime-local")] [InlineData("DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.0600000-05:00", "text")] [InlineData("time", "{0:t}", "03:04", "time")] + [InlineData("month", "{0:yyyy-MM}", "2000-01", "month")] [ReplaceCulture] public void Editor_FindsCorrectDateOrTimeTemplate_NotRfc3339( string dataTypeName, @@ -950,6 +954,7 @@ Environment.NewLine; [InlineData("datetime-local", null, "2000-01-02T03:04:05.060", "datetime-local")] [InlineData("DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.060Z", "text")] [InlineData("time", "{0:t}", "03:04:05.060", "time")] + [InlineData("month", "{0:yyyy-MM}", "2000-01", "month")] public void Editor_FindsCorrectDateOrTimeTemplate_ForDateTime( string dataTypeName, string editFormatString, @@ -1010,6 +1015,7 @@ Environment.NewLine; [InlineData("datetime-local", null, "02/01/2000 03:04:05", "datetime-local")] [InlineData("DateTimeOffset", "{0:o}", "2000-01-02T03:04:05.0600000Z", "text")] [InlineData("time", "{0:t}", "03:04", "time")] + [InlineData("month", "{0:yyyy-MM}", "2000-01", "month")] [ReplaceCulture] public void Editor_FindsCorrectDateOrTimeTemplate_ForDateTimeNotRfc3339( string dataTypeName, @@ -1076,6 +1082,8 @@ Environment.NewLine; [InlineData("datetime-local", Html5DateRenderingMode.Rfc3339, "datetime-local")] [InlineData("time", Html5DateRenderingMode.CurrentCulture, "time")] [InlineData("time", Html5DateRenderingMode.Rfc3339, "time")] + [InlineData("month", Html5DateRenderingMode.CurrentCulture, "month")] + [InlineData("month", Html5DateRenderingMode.Rfc3339, "month")] public void Editor_AppliesNonDefaultEditFormat(string dataTypeName, Html5DateRenderingMode renderingMode, string expectedType) { // Arrange