Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
1c67ad4
feat(blazor): add CssClass parameter to ValidationSummary component
EduardF1 Apr 29, 2026
b142fff
feat(blazor): add CssClass to ValidationSummary public API
EduardF1 Apr 29, 2026
9f2c80f
test(blazor): add CssClass ValidationSummary to E2E test component
EduardF1 Apr 29, 2026
88f0525
test(blazor): add E2E test for ValidationSummary CssClass parameter
EduardF1 Apr 29, 2026
0e5404b
fix(test): move FindElement inside Browser.Equal lambda to avoid race…
EduardF1 May 3, 2026
32f2917
test(blazor): add isolated component for ValidationSummary CssClass E…
EduardF1 May 4, 2026
e8ee879
test(blazor): remove duplicate ValidationSummary from TypicalValidati…
EduardF1 May 4, 2026
2030069
test(blazor): use isolated component in ValidationSummaryAppliesCssCl…
EduardF1 May 4, 2026
d700736
test(blazor): register ValidationSummaryWithCssClassComponent in test…
EduardF1 May 4, 2026
9f64eb9
fix(blazor): scope CssClass test changes to TypicalValidationComponent
EduardF1 May 5, 2026
72cbda6
fix(blazor): isolate CssClass test fixture to avoid duplicate Validat…
EduardF1 May 6, 2026
8b920ec
Merge branch 'main' into feat/validationsummary-cssclass
EduardF1 May 7, 2026
f77bed8
Merge branch 'main' into feat/validationsummary-cssclass
EduardF1 May 8, 2026
aa62a01
Merge branch 'main' into feat/validationsummary-cssclass
EduardF1 May 9, 2026
e940078
fix(test): remove razor license header, add CssClass+class interactio…
EduardF1 May 13, 2026
5789637
fix(test): add CssClass + AdditionalAttributes class interaction asse…
EduardF1 May 13, 2026
8d295ec
refactor: remove public CssClass parameter, use internal-only fix
EduardF1 May 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/Components/Web/src/Forms/ValidationSummary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ protected override void BuildRenderTree(RenderTreeBuilder builder)
first = false;

builder.OpenElement(0, "ul");
builder.AddAttribute(1, "class", "validation-errors");
builder.AddMultipleAttributes(2, AdditionalAttributes);
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttributeIfNotNullOrEmpty(2, "class",
AttributeUtilities.CombineClassNames(AdditionalAttributes, "validation-errors"));
}

builder.OpenElement(3, "li");
Expand Down
28 changes: 28 additions & 0 deletions src/Components/test/E2ETest/Tests/FormsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1096,4 +1096,32 @@ private bool ElementHasAttribute(IWebElement webElement, string attribute)
var jsExecutor = (IJavaScriptExecutor)Browser;
return (bool)jsExecutor.ExecuteScript($"return arguments[0].attributes['{attribute}'] !== undefined;", webElement);
}

[Fact]
public void ValidationSummaryCombinesAdditionalAttributesClassWithDefault()
{
var appElement = Browser.MountTestComponent<ValidationSummaryWithCssClassComponent>();
var nameInput = appElement.FindElement(By.ClassName("name")).FindElement(By.TagName("input"));
var submitButton = appElement.FindElement(By.CssSelector("button[type=submit]"));

// Make the form invalid to trigger rendering of the ValidationSummary elements
nameInput.SendKeys("01234567890123456789\t");
submitButton.Click();

// Default ValidationSummary renders with only "validation-errors" class.
Browser.Equal("validation-errors",
() => appElement.FindElement(By.ClassName("all-errors")).FindElement(By.TagName("ul")).GetDomAttribute("class"));

// ValidationSummary with class="pt-2" via AdditionalAttributes combines both:
// splatted class + fixed "validation-errors"
Browser.Equal("pt-2 validation-errors",
() => appElement.FindElement(By.ClassName("all-errors-with-class")).FindElement(By.TagName("ul")).GetDomAttribute("class"));

// Additional non-class attributes (e.g. data-testid) are also splatted
Browser.Equal("validation-errors",
() => appElement.FindElement(By.ClassName("all-errors-with-attr")).FindElement(By.TagName("ul")).GetDomAttribute("class"));
Browser.Equal("my-summary",
() => appElement.FindElement(By.ClassName("all-errors-with-attr")).FindElement(By.TagName("ul")).GetDomAttribute("data-testid"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Components.Forms

<EditForm EditContext="@editContext" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator />

<p class="name">
Name: <InputText @bind-Value="person.Name" placeholder="Enter your name" />
</p>

<button type="submit">Submit</button>

<p class="all-errors">
<ValidationSummary />
</p>
<p class="all-errors-with-class">
<ValidationSummary class="pt-2" />
</p>
<p class="all-errors-with-attr">
<ValidationSummary data-testid="my-summary" />
</p>
</EditForm>

@code {
private EditContext editContext = default!;
private Person person = new();

protected override void OnInitialized()
{
editContext = new EditContext(person);
}

private void HandleValidSubmit() { }

private class Person
{
[Required, MaxLength(10)]
public string Name { get; set; } = string.Empty;
}
}
1 change: 1 addition & 0 deletions src/Components/test/testassets/BasicTestApp/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<option value="BasicTestApp.FormsTest.SimpleValidationComponentUsingExperimentalValidator">Simple validation using experimental validator</option>
<option value="BasicTestApp.FormsTest.ModelLevelValidationComponent">Model-level validation</option>
<option value="BasicTestApp.FormsTest.TypicalValidationComponent">Typical validation</option>
<option value="BasicTestApp.FormsTest.ValidationSummaryWithCssClassComponent">Validation summary with CssClass</option>
<option value="BasicTestApp.MediaTest.ImageTestComponent">Image component tests</option>
<option value="BasicTestApp.MediaTest.VideoTestComponent">Video component tests</option>
<option value="BasicTestApp.MediaTest.FileDownloadTestComponent">File download component tests</option>
Expand Down
Loading