Skip to content

Commit 147cefb

Browse files
Copilotcsharpfritz
andauthored
Add ValidationGroup support for selective validation (#313)
Co-authored-by: csharpfritz <78577+csharpfritz@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 16f01e7 commit 147cefb

9 files changed

Lines changed: 524 additions & 2 deletions

File tree

docs/EditorControls/Button.md

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Original Microsoft documentation: https://docs.microsoft.com/en-us/dotnet/api/sy
1313
- `CommandName` - the command name passed to `OnCommand` event
1414
- `CommandArgument` - the command argument passed to `OnCommand` event
1515
- `CausesValidation` - controls whether form validation is triggered on click (default: `true`)
16+
- `ValidationGroup` - specifies the validation group for which the button triggers validation
1617
- `Enabled` - enables or disables the button
1718
- `Visible` - controls button visibility
1819
- `ToolTip` - tooltip text displayed on hover
@@ -28,7 +29,6 @@ Original Microsoft documentation: https://docs.microsoft.com/en-us/dotnet/api/sy
2829

2930
- **PostBackUrl** - Not supported; Blazor uses component events instead of postbacks to different pages
3031
- **UseSubmitBehavior** - Not supported; Blazor buttons trigger click events and you can inspect the form regardless
31-
- **ValidationGroup** - Not yet implemented; use EditForm validation instead
3232
- **AccessKey** - Use HTML `accesskey` attribute directly if needed
3333

3434
## Web Forms Declarative Syntax
@@ -153,6 +153,61 @@ Original Microsoft documentation: https://docs.microsoft.com/en-us/dotnet/api/sy
153153
</EditForm>
154154
```
155155

156+
### ValidationGroup - Selective Validation
157+
158+
The `ValidationGroup` property allows you to create multiple validation groups on a single form. When a button with a `ValidationGroup` is clicked, only validators with the matching `ValidationGroup` will be triggered.
159+
160+
**Important:** To use `ValidationGroup`, you must wrap your form in a `ValidationGroupProvider` component.
161+
162+
```razor
163+
@using BlazorWebFormsComponents.Validations
164+
165+
<ValidationGroupProvider>
166+
<EditForm Model="@model" OnValidSubmit="HandlePersonalSubmit">
167+
@* Personal Information Group *@
168+
<InputText @ref="NameInput.Current" @bind-Value="model.Name" />
169+
<RequiredFieldValidator ControlToValidate="@NameInput"
170+
Text="Name required"
171+
ValidationGroup="Personal" />
172+
173+
<InputText @ref="EmailInput.Current" @bind-Value="model.Email" />
174+
<RequiredFieldValidator ControlToValidate="@EmailInput"
175+
Text="Email required"
176+
ValidationGroup="Personal" />
177+
178+
<Button Text="Validate Personal" ValidationGroup="Personal" />
179+
</EditForm>
180+
181+
<EditForm Model="@model" OnValidSubmit="HandleBusinessSubmit">
182+
@* Business Information Group *@
183+
<InputText @ref="CompanyInput.Current" @bind-Value="model.Company" />
184+
<RequiredFieldValidator ControlToValidate="@CompanyInput"
185+
Text="Company required"
186+
ValidationGroup="Business" />
187+
188+
<Button Text="Validate Business" ValidationGroup="Business" />
189+
</EditForm>
190+
</ValidationGroupProvider>
191+
192+
@code {
193+
ForwardRef<InputBase<string>> NameInput = new ForwardRef<InputBase<string>>();
194+
ForwardRef<InputBase<string>> EmailInput = new ForwardRef<InputBase<string>>();
195+
ForwardRef<InputBase<string>> CompanyInput = new ForwardRef<InputBase<string>>();
196+
197+
private FormModel model = new FormModel();
198+
199+
void HandlePersonalSubmit() { /* Personal validation passed */ }
200+
void HandleBusinessSubmit() { /* Business validation passed */ }
201+
}
202+
```
203+
204+
**How ValidationGroup Works:**
205+
206+
1. **Same Group** - Button with `ValidationGroup="Personal"` triggers only validators with `ValidationGroup="Personal"`
207+
2. **No Group (empty/null)** - Button without a `ValidationGroup` triggers only validators without a `ValidationGroup`
208+
3. **Multiple Groups** - You can have multiple groups on the same page that validate independently
209+
4. **CausesValidation** - Set `CausesValidation="false"` to disable validation entirely for a button
210+
156211
## HTML Output
157212

158213
**Web Forms Input:**

docs/ValidationControls/RequiredFieldValidator.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,58 @@ Original Microsoft implementation of the ASP<span></span>.NET RequiredFieldValid
44

55
## Features supported in Blazor
66

7+
- `ControlToValidate` - Reference to the input control to validate (using `ForwardRef<InputBase<T>>`)
8+
- `Text` - Error message displayed inline when validation fails
9+
- `ErrorMessage` - Message shown in ValidationSummary
10+
- `ValidationGroup` - Group name for selective validation (see ValidationGroup section below)
11+
- `Enabled` - Enable or disable the validator
12+
- `Display` - How the error message is displayed (Static, Dynamic, None)
13+
- All style properties (`ForeColor`, `BackColor`, `CssClass`, etc.)
14+
15+
## ValidationGroup Support
16+
17+
The `ValidationGroup` property allows validators to participate in selective validation. When a button with a matching `ValidationGroup` is clicked, only validators in that group will validate.
18+
19+
**Key Points:**
20+
21+
1. Validators and buttons with the same `ValidationGroup` value work together
22+
2. Validators without a `ValidationGroup` are triggered by buttons without a `ValidationGroup`
23+
3. Must wrap form in `<ValidationGroupProvider>` to use `ValidationGroup`
24+
25+
**Example:**
26+
27+
```razor
28+
@using BlazorWebFormsComponents.Validations
29+
30+
<ValidationGroupProvider>
31+
<EditForm Model="@model">
32+
@* This validator is in the "Personal" group *@
33+
<InputText @ref="NameInput.Current" @bind-Value="model.Name" />
34+
<RequiredFieldValidator ControlToValidate="@NameInput"
35+
Text="Name is required"
36+
ValidationGroup="Personal" />
37+
38+
@* This validator is in the "Business" group *@
39+
<InputText @ref="CompanyInput.Current" @bind-Value="model.Company" />
40+
<RequiredFieldValidator ControlToValidate="@CompanyInput"
41+
Text="Company is required"
42+
ValidationGroup="Business" />
43+
44+
@* This button only validates the "Personal" group *@
45+
<Button Text="Validate Personal" ValidationGroup="Personal" />
46+
47+
@* This button only validates the "Business" group *@
48+
<Button Text="Validate Business" ValidationGroup="Business" />
49+
</EditForm>
50+
</ValidationGroupProvider>
51+
52+
@code {
53+
ForwardRef<InputBase<string>> NameInput = new ForwardRef<InputBase<string>>();
54+
ForwardRef<InputBase<string>> CompanyInput = new ForwardRef<InputBase<string>>();
55+
private FormModel model = new FormModel();
56+
}
57+
```
58+
759
## Web Forms Declarative Syntax
860

961
## Usage Notes

samples/AfterBlazorServerSide/Components/Pages/ControlSamples/Button/Nav.razor

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Other usage samples:
33
<NavLink href="./ControlSamples/Button" class="component-link" Match="NavLinkMatch.All">Simple Button</NavLink> |
44
<NavLink href="./ControlSamples/Button/CausesValidation" class="component-link" Match="NavLinkMatch.All">Causes Validation</NavLink> |
5+
<NavLink href="./ControlSamples/Button/ValidationGroup" class="component-link" Match="NavLinkMatch.All">Validation Group</NavLink> |
56
<NavLink href="./ControlSamples/Button/JavaScript" class="component-link" Match="NavLinkMatch.All">JavaScript Click</NavLink> |
67
<NavLink href="./ControlSamples/Button/Style" class="component-link" Match="NavLinkMatch.All">Button Style</NavLink> |
78
</div>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
@page "/ControlSamples/Button/ValidationGroup"
2+
@using BlazorWebFormsComponents.Validations
3+
@using static BlazorWebFormsComponents.WebColor
4+
5+
<h2>ValidationGroup Demo</h2>
6+
7+
<Nav></Nav>
8+
9+
<p>This demo shows how ValidationGroup allows different buttons to trigger validation for specific sets of validators.</p>
10+
11+
<ValidationGroupProvider>
12+
<EditForm Model="@model" OnValidSubmit="@HandlePersonalSubmit">
13+
14+
<fieldset style="border: 1px solid #ccc; padding: 15px; margin-bottom: 20px;">
15+
<legend>Personal Information (ValidationGroup="Personal")</legend>
16+
17+
<div style="margin-bottom: 10px;">
18+
<Label Text="Name:" AssociatedControlID="name" />
19+
<InputText id="name" @ref="NameInput.Current" @bind-Value="model.Name" style="margin-left: 10px;" />
20+
<RequiredFieldValidator ControlToValidate="@NameInput"
21+
Text="* Name is required"
22+
ErrorMessage="Name is required"
23+
ValidationGroup="Personal"
24+
Display="Dynamic"
25+
ForeColor="Red" />
26+
</div>
27+
28+
<div style="margin-bottom: 10px;">
29+
<Label Text="Email:" AssociatedControlID="email" />
30+
<InputText id="email" @ref="EmailInput.Current" @bind-Value="model.Email" style="margin-left: 10px;" />
31+
<RequiredFieldValidator ControlToValidate="@EmailInput"
32+
Text="* Email is required"
33+
ErrorMessage="Email is required"
34+
ValidationGroup="Personal"
35+
Display="Dynamic"
36+
ForeColor="Red" />
37+
</div>
38+
39+
<Button Text="Validate Personal Info"
40+
CausesValidation="true"
41+
ValidationGroup="Personal"
42+
BackColor="Blue"
43+
ForeColor="White" />
44+
</fieldset>
45+
46+
</EditForm>
47+
48+
<EditForm Model="@model" OnValidSubmit="@HandleBusinessSubmit">
49+
50+
<fieldset style="border: 1px solid #ccc; padding: 15px; margin-bottom: 20px;">
51+
<legend>Business Information (ValidationGroup="Business")</legend>
52+
53+
<div style="margin-bottom: 10px;">
54+
<Label Text="Company:" AssociatedControlID="company" />
55+
<InputText id="company" @ref="CompanyInput.Current" @bind-Value="model.Company" style="margin-left: 10px;" />
56+
<RequiredFieldValidator ControlToValidate="@CompanyInput"
57+
Text="* Company is required"
58+
ErrorMessage="Company is required"
59+
ValidationGroup="Business"
60+
Display="Dynamic"
61+
ForeColor="Red" />
62+
</div>
63+
64+
<div style="margin-bottom: 10px;">
65+
<Label Text="Phone:" AssociatedControlID="phone" />
66+
<InputText id="phone" @ref="PhoneInput.Current" @bind-Value="model.Phone" style="margin-left: 10px;" />
67+
<RequiredFieldValidator ControlToValidate="@PhoneInput"
68+
Text="* Phone is required"
69+
ErrorMessage="Phone is required"
70+
ValidationGroup="Business"
71+
Display="Dynamic"
72+
ForeColor="Red" />
73+
</div>
74+
75+
<Button Text="Validate Business Info"
76+
CausesValidation="true"
77+
ValidationGroup="Business"
78+
BackColor="Green"
79+
ForeColor="White" />
80+
</fieldset>
81+
82+
</EditForm>
83+
84+
<div style="margin-top: 20px;">
85+
<p><strong>Status:</strong> @statusMessage</p>
86+
</div>
87+
88+
</ValidationGroupProvider>
89+
90+
@code {
91+
92+
ForwardRef<InputBase<string>> NameInput = new ForwardRef<InputBase<string>>();
93+
ForwardRef<InputBase<string>> EmailInput = new ForwardRef<InputBase<string>>();
94+
ForwardRef<InputBase<string>> CompanyInput = new ForwardRef<InputBase<string>>();
95+
ForwardRef<InputBase<string>> PhoneInput = new ForwardRef<InputBase<string>>();
96+
97+
private FormModel model = new FormModel();
98+
private string statusMessage = "Ready";
99+
100+
public void HandlePersonalSubmit()
101+
{
102+
statusMessage = $"Personal Info Validated! Name: {model.Name}, Email: {model.Email}";
103+
}
104+
105+
public void HandleBusinessSubmit()
106+
{
107+
statusMessage = $"Business Info Validated! Company: {model.Company}, Phone: {model.Phone}";
108+
}
109+
110+
public class FormModel
111+
{
112+
public string Name { get; set; }
113+
public string Email { get; set; }
114+
public string Company { get; set; }
115+
public string Phone { get; set; }
116+
}
117+
118+
}

0 commit comments

Comments
 (0)