1
+ using FluentValidation ;
2
+ using FormCraft . DemoBlazorApp . Components . Shared ;
3
+ using FormCraft . DemoBlazorApp . Models ;
4
+ using Microsoft . AspNetCore . Components ;
5
+ using MudBlazor ;
6
+
7
+ namespace FormCraft . DemoBlazorApp . Components . Pages ;
8
+
9
+ public partial class FluentValidationDemo : ComponentBase
10
+ {
11
+ private CustomerModel _model = new ( ) ;
12
+ private IFormConfiguration < CustomerModel > ? _formConfig ;
13
+ private bool _submitted ;
14
+ private bool _isSubmitting ;
15
+ private int _validationAttempts ;
16
+ private int _successfulValidations ;
17
+
18
+ private readonly List < FormGuidelines . GuidelineItem > _sidebarFeatures =
19
+ [
20
+ new ( )
21
+ {
22
+ Icon = Icons . Material . Filled . Merge ,
23
+ Color = Color . Primary ,
24
+ Text = "Seamless integration with existing validators"
25
+ } ,
26
+
27
+ new ( )
28
+ {
29
+ Icon = Icons . Material . Filled . Rule ,
30
+ Color = Color . Secondary ,
31
+ Text = "Support for complex validation rules"
32
+ } ,
33
+
34
+ new ( )
35
+ {
36
+ Icon = Icons . Material . Filled . CloudSync ,
37
+ Color = Color . Tertiary ,
38
+ Text = "Async validation support"
39
+ } ,
40
+
41
+ new ( )
42
+ {
43
+ Icon = Icons . Material . Filled . AccountTree ,
44
+ Color = Color . Info ,
45
+ Text = "Nested object validation"
46
+ } ,
47
+
48
+ new ( )
49
+ {
50
+ Icon = Icons . Material . Filled . Message ,
51
+ Color = Color . Success ,
52
+ Text = "Custom error messages"
53
+ } ,
54
+
55
+ new ( )
56
+ {
57
+ Icon = Icons . Material . Filled . FilterAlt ,
58
+ Color = Color . Warning ,
59
+ Text = "Conditional validation logic"
60
+ }
61
+ ] ;
62
+
63
+ private readonly List < GuidelineItem > _apiGuidelineTableItems =
64
+ [
65
+ new ( )
66
+ {
67
+ Feature = "WithFluentValidation()" ,
68
+ Usage = "Uses validator registered in DI" ,
69
+ Example = "field.WithFluentValidation(x => x.Email)"
70
+ } ,
71
+
72
+ new ( )
73
+ {
74
+ Feature = "WithFluentValidator()" ,
75
+ Usage = "Uses specific validator instance" ,
76
+ Example = "field.WithFluentValidator(validator, x => x.Name)"
77
+ } ,
78
+
79
+ new ( )
80
+ {
81
+ Feature = "Register Validators" ,
82
+ Usage = "Add to dependency injection" ,
83
+ Example = "services.AddScoped<IValidator<Model>, ModelValidator>()"
84
+ } ,
85
+
86
+ new ( )
87
+ {
88
+ Feature = "Combine Validators" ,
89
+ Usage = "Mix with FormCraft validators" ,
90
+ Example = "field.Required().WithFluentValidation(x => x.Name)"
91
+ } ,
92
+
93
+ new ( )
94
+ {
95
+ Feature = "Nested Validation" ,
96
+ Usage = "Supports SetValidator rules" ,
97
+ Example = "RuleFor(x => x.Address).SetValidator(new AddressValidator())"
98
+ } ,
99
+
100
+ new ( )
101
+ {
102
+ Feature = "Async Rules" ,
103
+ Usage = "Supports MustAsync" ,
104
+ Example = "RuleFor(x => x.Email).MustAsync(async (email, ct) => ...)"
105
+ }
106
+ ] ;
107
+
108
+ protected override void OnInitialized ( )
109
+ {
110
+ // Create form configuration using FluentValidation
111
+ _formConfig = FormBuilder < CustomerModel >
112
+ . Create ( )
113
+ . AddField ( x => x . Name , field => field
114
+ . WithLabel ( "Customer Name" )
115
+ . WithPlaceholder ( "Enter your full name" )
116
+ . WithFluentValidation ( x => x . Name )
117
+ . WithHelpText ( "Name must be between 3 and 50 characters" ) )
118
+ . AddField ( x => x . Email , field => field
119
+ . WithLabel ( "Email Address" )
120
+ . WithPlaceholder ( "your.email@example.com" )
121
+ . WithFluentValidation ( x => x . Email )
122
+ . WithHelpText ( "We'll never share your email with anyone" ) )
123
+ . AddField ( x => x . Age , field => field
124
+ . WithLabel ( "Age" )
125
+ . WithPlaceholder ( "18" )
126
+ . WithFluentValidation ( x => x . Age )
127
+ . WithHelpText ( "Must be 18 or older" ) )
128
+ . Build ( ) ;
129
+ }
130
+
131
+ private async Task HandleValidSubmit ( CustomerModel model )
132
+ {
133
+ _isSubmitting = true ;
134
+ _validationAttempts ++ ;
135
+ StateHasChanged ( ) ;
136
+
137
+ // Simulate async operation
138
+ await Task . Delay ( 1500 ) ;
139
+
140
+ _submitted = true ;
141
+ _successfulValidations ++ ;
142
+ _isSubmitting = false ;
143
+ StateHasChanged ( ) ;
144
+ }
145
+
146
+ private Task HandleFieldChanged ( ( string fieldName , object ? value ) args )
147
+ {
148
+ // Track field changes if needed
149
+ return Task . CompletedTask ;
150
+ }
151
+
152
+ private void ResetForm ( )
153
+ {
154
+ _model = new CustomerModel ( ) ;
155
+ _submitted = false ;
156
+ StateHasChanged ( ) ;
157
+ }
158
+
159
+ private List < FormSuccessDisplay . DataDisplayItem > GetDataDisplayItems ( )
160
+ {
161
+ return new List < FormSuccessDisplay . DataDisplayItem >
162
+ {
163
+ new ( ) { Label = "Customer Name" , Value = _model . Name } ,
164
+ new ( ) { Label = "Email Address" , Value = _model . Email } ,
165
+ new ( ) { Label = "Age" , Value = _model . Age . ToString ( ) } ,
166
+ new ( ) { Label = "Validation Type" , Value = "FluentValidation" } ,
167
+ new ( ) { Label = "Validator Class" , Value = "CustomerValidator" }
168
+ } ;
169
+ }
170
+
171
+ private string GetCodeExample ( )
172
+ {
173
+ return @"// 1. Define your FluentValidation validator
174
+ public class CustomerValidator : AbstractValidator<Customer>
175
+ {
176
+ public CustomerValidator()
177
+ {
178
+ RuleFor(x => x.Name)
179
+ .NotEmpty().WithMessage(""Name is required"")
180
+ .MinimumLength(3).WithMessage(""Name must be at least 3 characters"")
181
+ .MaximumLength(50).WithMessage(""Name cannot exceed 50 characters"");
182
+
183
+ RuleFor(x => x.Email)
184
+ .NotEmpty().WithMessage(""Email is required"")
185
+ .EmailAddress().WithMessage(""Invalid email format"");
186
+
187
+ RuleFor(x => x.Age)
188
+ .GreaterThanOrEqualTo(18).WithMessage(""Must be 18 or older"");
189
+ }
190
+ }
191
+
192
+ // 2. Register the validator in DI
193
+ services.AddScoped<IValidator<Customer>, CustomerValidator>();
194
+
195
+ // 3. Use in FormCraft
196
+ var formConfig = FormBuilder<Customer>
197
+ .Create()
198
+ .AddField(x => x.Name, field => field
199
+ .WithLabel(""Customer Name"")
200
+ .WithFluentValidation(x => x.Name))
201
+ .AddField(x => x.Email, field => field
202
+ .WithLabel(""Email Address"")
203
+ .WithFluentValidation(x => x.Email))
204
+ .Build();" ;
205
+ }
206
+
207
+ // Model class
208
+ public class CustomerModel
209
+ {
210
+ public string Name { get ; set ; } = "" ;
211
+ public string Email { get ; set ; } = "" ;
212
+ public int Age { get ; set ; }
213
+ }
214
+
215
+ // FluentValidation validator
216
+ public class CustomerValidator : AbstractValidator < CustomerModel >
217
+ {
218
+ public CustomerValidator ( )
219
+ {
220
+ RuleFor ( x => x . Name )
221
+ . NotEmpty ( ) . WithMessage ( "Name is required" )
222
+ . MinimumLength ( 3 ) . WithMessage ( "Name must be at least 3 characters" )
223
+ . MaximumLength ( 50 ) . WithMessage ( "Name cannot exceed 50 characters" ) ;
224
+
225
+ RuleFor ( x => x . Email )
226
+ . NotEmpty ( ) . WithMessage ( "Email is required" )
227
+ . EmailAddress ( ) . WithMessage ( "Please enter a valid email address" ) ;
228
+
229
+ RuleFor ( x => x . Age )
230
+ . GreaterThanOrEqualTo ( 18 ) . WithMessage ( "You must be 18 or older" ) ;
231
+ }
232
+ }
233
+ }
0 commit comments