+ {
+ EditContext = editContext,
+ ValueChanged = value => model.DateProperty = value,
+ ValueExpression = () => model.DateProperty
+ };
+ var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty);
+ var unrelatedFieldIdentifier = FieldIdentifier.Create(() => model.StringProperty);
+ var unrelatedMessages = new ValidationMessageStore(editContext);
+ var fieldChangedCount = 0;
+ editContext.OnFieldChanged += (sender, eventArgs) =>
+ {
+ fieldChangedCount++;
+ unrelatedMessages.Add(unrelatedFieldIdentifier, "Unrelated validation ran");
+ };
+ var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
+ await inputComponent.SetCurrentValueAsStringAsync("1991/11/20");
+ unrelatedMessages.Clear();
+ editContext.MarkAsUnmodified(fieldIdentifier);
+
+ await inputComponent.SetCurrentValueAsStringAsync("1991/11/40");
+
+ Assert.Equal(new DateTime(1991, 11, 20), model.DateProperty);
+ Assert.True(editContext.IsModified(fieldIdentifier));
+ Assert.Equal(1, fieldChangedCount);
+ Assert.Equal(new[] { "Bad date value" }, editContext.GetValidationMessages(fieldIdentifier));
+ Assert.Empty(editContext.GetValidationMessages(unrelatedFieldIdentifier));
+ Assert.False(editContext.IsModified(unrelatedFieldIdentifier));
}
[Fact]
diff --git a/src/Components/test/E2ETest/Tests/FormsTest.cs b/src/Components/test/E2ETest/Tests/FormsTest.cs
index 21a982e107c1..36a602cdf301 100644
--- a/src/Components/test/E2ETest/Tests/FormsTest.cs
+++ b/src/Components/test/E2ETest/Tests/FormsTest.cs
@@ -186,6 +186,43 @@ public void InputNumberInteractsWithEditContext_NullableFloat()
Browser.Empty(messagesAccessor);
}
+ [Fact]
+ public void InputNumberParsingFailureDoesNotTriggerModelValidation()
+ {
+ var appElement = MountTypicalValidationComponent();
+ var input = appElement.FindElement(By.ClassName("required-number")).FindElement(By.TagName("input"));
+ var value = appElement.FindElement(By.ClassName("required-number-value"));
+ var messagesAccessor = CreateValidationMessagesAccessor(appElement);
+
+ input.SendKeys("1e+10\t");
+
+ Browser.Equal("modified invalid", () => input.GetDomAttribute("class"));
+ Browser.Equal("", () => value.Text);
+ Browser.Equal(new[] { "The RequiredNumber field must be a number." }, messagesAccessor);
+
+ input.Clear();
+ input.SendKeys("5\t");
+
+ Browser.Equal("modified valid", () => input.GetDomAttribute("class"));
+ Browser.Equal("5", () => value.Text);
+ Browser.Empty(messagesAccessor);
+
+ input.SendKeys(Keys.Control + "a");
+ input.SendKeys(Keys.Delete);
+ input.SendKeys("1e+10\t");
+
+ Browser.Equal("modified invalid", () => input.GetDomAttribute("class"));
+ Browser.Equal("5", () => value.Text);
+ Browser.Equal(new[] { "The RequiredNumber field must be a number." }, messagesAccessor);
+
+ input.Clear();
+ input.SendKeys("\t");
+
+ Browser.Equal("modified invalid", () => input.GetDomAttribute("class"));
+ Browser.Equal("", () => value.Text);
+ Browser.Equal(new[] { "Enter a required number" }, messagesAccessor);
+ }
+
[Fact]
public void InputTextAreaInteractsWithEditContext()
{
diff --git a/src/Components/test/testassets/BasicTestApp/FormsTest/TypicalValidationComponent.razor b/src/Components/test/testassets/BasicTestApp/FormsTest/TypicalValidationComponent.razor
index 27e09dd7846f..d12cfe3fe051 100644
--- a/src/Components/test/testassets/BasicTestApp/FormsTest/TypicalValidationComponent.razor
+++ b/src/Components/test/testassets/BasicTestApp/FormsTest/TypicalValidationComponent.razor
@@ -24,6 +24,10 @@
Height (optional):
+
+ Required number:
+ @person.RequiredNumber
+
Description:
@@ -185,6 +189,9 @@
public float? OptionalHeight { get; set; }
+ [Required(ErrorMessage = "Enter a required number")]
+ public int? RequiredNumber { get; set; }
+
public DateTime RenewalDate { get; set; } = DateTime.Now;
public DateTimeOffset? OptionalExpiryDate { get; set; }