Skip to content

Commit 5cc9b72

Browse files
882857: Added form validation topic for blazor stepper.
1 parent c8e121c commit 5cc9b72

File tree

2 files changed

+312
-2
lines changed

2 files changed

+312
-2
lines changed

blazor/stepper/images/edit-form.png

19.6 KB
Loading

blazor/stepper/steps-validation.md

Lines changed: 312 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ documentation: ug
99

1010
# Steps validation in Blazor Stepper Component
1111

12-
The Stepper control allows you to set the validation state for each step, displaying either a success or error icon. You can define the success state of a step by setting the [IsValid](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Navigations.StepperStep.html#Syncfusion_Blazor_Navigations_StepperStep_IsValid) property to `true`. If set to `false`, the step will display an error state. By default, the `IsValid` property is `null`.
12+
The Stepper component allows you to set the validation state for each step, displaying either a success or error icon. You can define the success state of a step by setting the [IsValid](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Navigations.StepperStep.html#Syncfusion_Blazor_Navigations_StepperStep_IsValid) property to `true`. If set to `false`, the step will display an error state. By default, the `IsValid` property is `null`.
1313

1414
> Based on the `StepType`, the validation state icon will be displayed either as an indicator or as part of the step label/text.
1515
@@ -68,4 +68,314 @@ The Stepper control allows you to set the validation state for each step, displa
6868
6969
```
7070

71-
![Blazor Stepper Component with Validation](./images/Blazor-validation.png)
71+
![Blazor Stepper Component with Validation](./images/Blazor-validation.png)
72+
73+
## Validating fields
74+
75+
You can validate the fields within the stepper component. In the below shared example, as the user progress through steps they enter information, receive feedback, and confirm submission. Validation messages will appear for errors, and a success message confirms the completion.
76+
77+
```cshtml
78+
79+
@using Syncfusion.Blazor.Navigations
80+
@using System.ComponentModel.DataAnnotations
81+
82+
<SfStepper @ref="stepper" StepChanging="@handleStepChange" Linear=true>
83+
<StepperSteps>
84+
<StepperStep @ref="stepperStep1" IconCss="sf-icon-survey-intro" Text="Survey Info"></StepperStep>
85+
<StepperStep @ref="stepperStep2" IconCss="sf-icon-survey-feedback" Text="Feedback"></StepperStep>
86+
<StepperStep @ref="stepperStep3" IconCss="sf-icon-survey-status" Text="Status"></StepperStep>
87+
</StepperSteps>
88+
</SfStepper>
89+
90+
<EditForm Model="@model">
91+
<DataAnnotationsValidator />
92+
<div class="form-container">
93+
<div class="valid-form">
94+
@if (currentStep == 1)
95+
{
96+
<div class="form-group">
97+
<label for="name">Enter your name:</label>
98+
<div class="validation-container">
99+
<InputText id="name" @bind-Value="@model.Name" width="350px" />
100+
<ValidationMessage For="@(() => model.Name)" />
101+
</div>
102+
</div>
103+
<div class="form-group">
104+
<label for="email">Enter your e-mail:</label>
105+
<div class="validation-container">
106+
<InputText id="email" @bind-Value="@model.Email"/>
107+
<ValidationMessage For="@(() => model.Email)" />
108+
</div>
109+
</div>
110+
}
111+
else if (currentStep == 2)
112+
{
113+
<div class="feedback-form">
114+
<p>Anything else you'd like to share?</p>
115+
<div class="validation-container">
116+
<InputTextArea id="Feedback" @bind-Value="@model.Feedback"></InputTextArea>
117+
@if (!string.IsNullOrEmpty(model.Feedback) && model.Feedback.Length < 5)
118+
{
119+
<div class="validation-message">Please enter at least 5 characters.</div>
120+
}
121+
</div>
122+
</div>
123+
}
124+
</div>
125+
<div class="btn-container">
126+
@if (currentStep == 2)
127+
{
128+
<button type="submit" style="margin: 10px;" class="e-btn" @onclick="@onPreviousStep"> Previous </button>
129+
}
130+
@if (currentStep != 3)
131+
{
132+
content = "";
133+
<button type="submit" style="margin: 10px;" class="e-btn" @onclick="@onNextStep">@(currentStep == 1 ? "Next" : "Submit Feedback")</button>
134+
}
135+
</div>
136+
<h5 style="color: green; margin-top: 20px;">@content</h5>
137+
@if (currentStep == 3)
138+
{
139+
if (showFeedBack)
140+
{
141+
<h6><b>Please confirm to submit your feedback.</b></h6>
142+
<p>@model.Feedback</p>
143+
<div class="btn-container">
144+
<button type="submit" style="margin: 10px;" class="e-btn" @onclick="@onPreviousStep"> Previous </button>
145+
<button type="submit" class="e-btn" @onclick="@orderConfirm">Confirm</button>
146+
</div>
147+
}
148+
else
149+
{
150+
<button type="submit" style="margin: 10px;" class="e-btn" @onclick="@onReset"> Reset </button>
151+
}
152+
}
153+
</div>
154+
</EditForm>
155+
156+
@code {
157+
private StepperModel model = new StepperModel();
158+
private SfStepper stepper;
159+
private StepperStep stepperStep1;
160+
private StepperStep stepperStep2;
161+
private StepperStep stepperStep3;
162+
private int currentStep = 1;
163+
private bool isValid = false;
164+
private string content = "";
165+
private bool isValidMsg = false;
166+
private bool showFeedBack = false;
167+
168+
private async void onNextStep()
169+
{
170+
await stepper.NextStepAsync();
171+
}
172+
private async void onPreviousStep()
173+
{
174+
await stepper.PreviousStepAsync();
175+
}
176+
private async void onReset()
177+
{
178+
currentStep = 1;
179+
await stepper.ResetAsync();
180+
model = new StepperModel();
181+
StateHasChanged();
182+
}
183+
184+
private void orderConfirm()
185+
{
186+
if (isValid && currentStep == 3)
187+
{
188+
content = "Thanks! Feedback has been submitted successfully.";
189+
showFeedBack = false;
190+
}
191+
}
192+
193+
private void handleStepChange(StepperChangeEventArgs args)
194+
{
195+
if (args.ActiveStep != args.PreviousStep || currentStep == 3)
196+
{
197+
isValid = false;
198+
switch (currentStep)
199+
{
200+
case 1:
201+
if (ValidateCurrentStep() && !string.IsNullOrEmpty(model.Name))
202+
{
203+
stepperStep1.IsValid = true;
204+
if (args.ActiveStep < args.PreviousStep)
205+
{
206+
stepperStep1.IsValid = null;
207+
stepperStep2.IsValid = null;
208+
stepperStep3.IsValid = null;
209+
}
210+
else
211+
{
212+
currentStep++;
213+
}
214+
args.Cancel = false;
215+
}
216+
else
217+
{
218+
stepperStep1.IsValid = false;
219+
args.Cancel = true;
220+
}
221+
break;
222+
case 2:
223+
if (!string.IsNullOrEmpty(model.Feedback) && model.Feedback.Length >= 5)
224+
{
225+
stepperStep2.IsValid = isValid = true;
226+
if (args.ActiveStep < args.PreviousStep)
227+
{
228+
currentStep = currentStep - 1;
229+
stepperStep2.IsValid = null;
230+
if (args.ActiveStep == 0)
231+
{
232+
stepperStep1.IsValid = null;
233+
}
234+
}
235+
else
236+
{
237+
currentStep++;
238+
showFeedBack = true;
239+
}
240+
args.Cancel = false;
241+
}
242+
else
243+
{
244+
if (args.ActiveStep == 0)
245+
{
246+
stepperStep1.IsValid = null;
247+
currentStep -= 1;
248+
args.Cancel = false;
249+
}
250+
else
251+
{
252+
stepperStep2.IsValid = isValid = false;
253+
args.Cancel = isValidMsg = true;
254+
}
255+
}
256+
break;
257+
case 3:
258+
stepperStep3.IsValid = true;
259+
if (args.ActiveStep < args.PreviousStep)
260+
{
261+
currentStep = currentStep - 1;
262+
stepperStep2.IsValid = stepperStep3.IsValid = null;
263+
}
264+
break;
265+
}
266+
}
267+
}
268+
269+
private bool ValidateCurrentStep()
270+
{
271+
bool isStepValid = true;
272+
var context = new ValidationContext(model);
273+
var validationResults = new List<ValidationResult>();
274+
isStepValid = Validator.TryValidateObject(model, context, validationResults, true);
275+
276+
if (currentStep == 1)
277+
{
278+
isStepValid = validationResults.All(result => result.MemberNames.Contains(nameof(StepperModel.Email)) == false || result.ErrorMessage == null);
279+
}
280+
281+
return isStepValid;
282+
}
283+
284+
public class StepperModel
285+
{
286+
[Required(ErrorMessage = "Please enter your name")]
287+
public string Name { get; set; }
288+
289+
[Required(ErrorMessage = "Please enter your email address")]
290+
[EmailAddress(ErrorMessage = "Invalid email address")]
291+
public string Email { get; set; }
292+
293+
[Required(ErrorMessage = "Please enter your feedback")]
294+
[MinLength(5)]
295+
public string Feedback { get; set; }
296+
}
297+
}
298+
299+
<style>
300+
@@font-face {
301+
font-family: 'Survey-icons';
302+
src: url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype');
303+
font-weight: normal;
304+
font-style: normal;
305+
}
306+
307+
[class^="sf-icon-"],
308+
[class*=" sf-icon-"] {
309+
font-family: 'Survey-icons' !important;
310+
speak: none;
311+
font-size: 55px;
312+
font-style: normal;
313+
font-weight: normal;
314+
font-variant: normal;
315+
text-transform: none;
316+
line-height: inherit;
317+
-webkit-font-smoothing: antialiased;
318+
-moz-osx-font-smoothing: grayscale;
319+
}
320+
321+
.sf-icon-survey-feedback:before {
322+
content: "\e700";
323+
}
324+
325+
.sf-icon-survey-intro:before {
326+
content: "\e703";
327+
}
328+
329+
.sf-icon-survey-status:before {
330+
content: "\e707";
331+
}
332+
333+
label {
334+
min-width: 135px;
335+
}
336+
337+
.validation-container input {
338+
width: 350px;
339+
}
340+
341+
.validation-container textarea {
342+
width: 400px;
343+
}
344+
345+
.form-container {
346+
margin: 0 auto;
347+
width: fit-content;
348+
display: flex;
349+
align-items: center;
350+
justify-content: center;
351+
flex-direction: column;
352+
}
353+
354+
.btn-container {
355+
display: flex;
356+
align-items: center;
357+
justify-content: center;
358+
}
359+
360+
.form-group,
361+
.feedback-container {
362+
margin: 20px 0px;
363+
}
364+
365+
.form-group {
366+
display: flex;
367+
}
368+
369+
.validation-message {
370+
font-size: 14px;
371+
}
372+
373+
.valid-form {
374+
margin-top: 20px;
375+
padding: 0 10px;
376+
}
377+
</style>
378+
379+
```
380+
381+
![Validation using editform](./images/edit-form.png)

0 commit comments

Comments
 (0)