Skip to content

Commit be90006

Browse files
authored
Validation: add warning feedback support (#6570)
* ValidationWarning * demo * docs * improve rendering
1 parent 29f65ff commit be90006

97 files changed

Lines changed: 3353 additions & 158 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Demos/Blazorise.Demo/Pages/Tests/ValidationsPage.razor

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,37 @@
255255
</Card>
256256
</Column>
257257
</Row>
258+
<Row>
259+
<Column ColumnSize="ColumnSize.IsFull.OnMobile.IsHalf.OnTablet">
260+
<Card Margin="Margin.Is4.OnY">
261+
<CardHeader>
262+
<CardTitle>Validation Feedback</CardTitle>
263+
</CardHeader>
264+
<CardBody>
265+
<CardText>Example on how to use the <code>ValidationFeedback</code> component for all validation states.</CardText>
266+
</CardBody>
267+
<CardBody>
268+
<Validations Mode="ValidationMode.Auto" ValidateOnLoad="false">
269+
<Validation Validator="@ValidateFeedbackName">
270+
<Field>
271+
<FieldLabel RequiredIndicator>Display name</FieldLabel>
272+
<TextInput Placeholder="Enter display name" @bind-Value="@feedbackName">
273+
<Feedback>
274+
<ValidationFeedback>
275+
<None>Please enter a display name.</None>
276+
<Warning>Short display names are allowed, but longer names are easier to recognize.</Warning>
277+
<Success>Display name looks good.</Success>
278+
<Error>Display name is required.</Error>
279+
</ValidationFeedback>
280+
</Feedback>
281+
</TextInput>
282+
</Field>
283+
</Validation>
284+
</Validations>
285+
</CardBody>
286+
</Card>
287+
</Column>
288+
</Row>
258289
<Row>
259290
<Column ColumnSize="ColumnSize.IsFull.OnMobile.IsHalf.OnTablet">
260291
<Card Margin="Margin.Is4.OnY">
@@ -636,6 +667,7 @@
636667

637668
string passwordAuto;
638669
string passwordManual;
670+
string feedbackName;
639671

640672
Random random = new();
641673

@@ -715,6 +747,24 @@
715747
}
716748
}
717749

750+
void ValidateFeedbackName( ValidatorEventArgs e )
751+
{
752+
string displayName = Convert.ToString( e.Value );
753+
754+
if ( string.IsNullOrWhiteSpace( displayName ) )
755+
{
756+
e.Status = ValidationStatus.Error;
757+
}
758+
else if ( displayName.Length < 4 )
759+
{
760+
e.Status = ValidationStatus.Warning;
761+
}
762+
else
763+
{
764+
e.Status = ValidationStatus.Success;
765+
}
766+
}
767+
718768
async Task Submit()
719769
{
720770
if ( await validations.ValidateAll() )

Documentation/Blazorise.Docs/Models/Snippets.generated.cs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4888,20 +4888,49 @@ async Task Submit()
48884888
</TextInput>
48894889
</Validation>";
48904890

4891-
public const string ValidationFeedbackExample = @"<Validation Validator=""@ValidateCheck"">
4892-
<Check TValue=""bool"">
4893-
<ChildContent>
4894-
Check me out
4895-
</ChildContent>
4891+
public const string ValidationFeedbackExample = @"<Validation Validator=""@ValidateDisplayName"">
4892+
<TextInput Placeholder=""Enter display name"">
48964893
<Feedback>
4897-
<ValidationError>You must check me out!</ValidationError>
4894+
<ValidationNone>Please enter a display name.</ValidationNone>
4895+
<ValidationWarning>Short display names are allowed, but longer names are easier to recognize.</ValidationWarning>
4896+
<ValidationSuccess>Display name looks good.</ValidationSuccess>
4897+
<ValidationError>Display name is required.</ValidationError>
48984898
</Feedback>
4899-
</Check>
4899+
</TextInput>
4900+
</Validation>
4901+
4902+
<Validation Validator=""@ValidateUserName"">
4903+
<TextInput Placeholder=""Enter username"">
4904+
<Feedback>
4905+
<ValidationFeedback>
4906+
<None>Please enter a username.</None>
4907+
<Warning>Short usernames are allowed, but longer usernames are easier to identify.</Warning>
4908+
<Success>Username looks good.</Success>
4909+
<Error>Username is required.</Error>
4910+
</ValidationFeedback>
4911+
</Feedback>
4912+
</TextInput>
49004913
</Validation>
49014914
@code{
4902-
void ValidateCheck( ValidatorEventArgs e )
4915+
void ValidateDisplayName( ValidatorEventArgs e )
4916+
{
4917+
ValidateNameLength( e );
4918+
}
4919+
4920+
void ValidateUserName( ValidatorEventArgs e )
49034921
{
4904-
// ...
4922+
ValidateNameLength( e );
4923+
}
4924+
4925+
void ValidateNameLength( ValidatorEventArgs e )
4926+
{
4927+
var name = Convert.ToString( e.Value );
4928+
4929+
e.Status = string.IsNullOrWhiteSpace( name )
4930+
? ValidationStatus.Error
4931+
: name.Length < 4
4932+
? ValidationStatus.Warning
4933+
: ValidationStatus.Success;
49054934
}
49064935
}";
49074936

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,51 @@
11
<div class="blazorise-codeblock">
22
<div class="html"><pre>
3-
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">Validation</span> <span class="htmlAttributeName">Validator</span><span class="htmlOperator">=</span><span class="quot">&quot;</span><span class="sharpVariable"><span class="atSign">&#64;</span>ValidateCheck</span><span class="quot">&quot;</span><span class="htmlTagDelimiter">&gt;</span>
4-
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">Check</span> <span class="htmlAttributeName">TValue</span><span class="htmlOperator">=</span><span class="quot">&quot;</span><span class="htmlAttributeValue">bool</span><span class="quot">&quot;</span><span class="htmlTagDelimiter">&gt;</span>
5-
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">ChildContent</span><span class="htmlTagDelimiter">&gt;</span>
6-
Check me out
7-
<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">ChildContent</span><span class="htmlTagDelimiter">&gt;</span>
3+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">Validation</span> <span class="htmlAttributeName">Validator</span><span class="htmlOperator">=</span><span class="quot">&quot;</span><span class="sharpVariable"><span class="atSign">&#64;</span>ValidateDisplayName</span><span class="quot">&quot;</span><span class="htmlTagDelimiter">&gt;</span>
4+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">TextInput</span> <span class="htmlAttributeName">Placeholder</span><span class="htmlOperator">=</span><span class="quot">&quot;</span><span class="htmlAttributeValue">Enter display name</span><span class="quot">&quot;</span><span class="htmlTagDelimiter">&gt;</span>
85
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">Feedback</span><span class="htmlTagDelimiter">&gt;</span>
9-
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">ValidationError</span><span class="htmlTagDelimiter">&gt;</span>You must check me out!<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">ValidationError</span><span class="htmlTagDelimiter">&gt;</span>
6+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">ValidationNone</span><span class="htmlTagDelimiter">&gt;</span>Please enter a display name.<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">ValidationNone</span><span class="htmlTagDelimiter">&gt;</span>
7+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">ValidationWarning</span><span class="htmlTagDelimiter">&gt;</span>Short display names are allowed, but longer names are easier to recognize.<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">ValidationWarning</span><span class="htmlTagDelimiter">&gt;</span>
8+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">ValidationSuccess</span><span class="htmlTagDelimiter">&gt;</span>Display name looks good.<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">ValidationSuccess</span><span class="htmlTagDelimiter">&gt;</span>
9+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">ValidationError</span><span class="htmlTagDelimiter">&gt;</span>Display name is required.<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">ValidationError</span><span class="htmlTagDelimiter">&gt;</span>
1010
<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">Feedback</span><span class="htmlTagDelimiter">&gt;</span>
11-
<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">Check</span><span class="htmlTagDelimiter">&gt;</span>
11+
<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">TextInput</span><span class="htmlTagDelimiter">&gt;</span>
12+
<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">Validation</span><span class="htmlTagDelimiter">&gt;</span>
13+
14+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">Validation</span> <span class="htmlAttributeName">Validator</span><span class="htmlOperator">=</span><span class="quot">&quot;</span><span class="sharpVariable"><span class="atSign">&#64;</span>ValidateUserName</span><span class="quot">&quot;</span><span class="htmlTagDelimiter">&gt;</span>
15+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">TextInput</span> <span class="htmlAttributeName">Placeholder</span><span class="htmlOperator">=</span><span class="quot">&quot;</span><span class="htmlAttributeValue">Enter username</span><span class="quot">&quot;</span><span class="htmlTagDelimiter">&gt;</span>
16+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">Feedback</span><span class="htmlTagDelimiter">&gt;</span>
17+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">ValidationFeedback</span><span class="htmlTagDelimiter">&gt;</span>
18+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">None</span><span class="htmlTagDelimiter">&gt;</span>Please enter a username.<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">None</span><span class="htmlTagDelimiter">&gt;</span>
19+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">Warning</span><span class="htmlTagDelimiter">&gt;</span>Short usernames are allowed, but longer usernames are easier to identify.<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">Warning</span><span class="htmlTagDelimiter">&gt;</span>
20+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">Success</span><span class="htmlTagDelimiter">&gt;</span>Username looks good.<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">Success</span><span class="htmlTagDelimiter">&gt;</span>
21+
<span class="htmlTagDelimiter">&lt;</span><span class="htmlElementName">Error</span><span class="htmlTagDelimiter">&gt;</span>Username is required.<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">Error</span><span class="htmlTagDelimiter">&gt;</span>
22+
<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">ValidationFeedback</span><span class="htmlTagDelimiter">&gt;</span>
23+
<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">Feedback</span><span class="htmlTagDelimiter">&gt;</span>
24+
<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">TextInput</span><span class="htmlTagDelimiter">&gt;</span>
1225
<span class="htmlTagDelimiter">&lt;/</span><span class="htmlElementName">Validation</span><span class="htmlTagDelimiter">&gt;</span>
1326
</pre></div>
1427
<div class="csharp"><pre>
1528
<span class="atSign">&#64;</span>code{
16-
<span class="keyword">void</span> ValidateCheck( ValidatorEventArgs e )
29+
<span class="keyword">void</span> ValidateDisplayName( ValidatorEventArgs e )
30+
{
31+
ValidateNameLength( e );
32+
}
33+
34+
<span class="keyword">void</span> ValidateUserName( ValidatorEventArgs e )
35+
{
36+
ValidateNameLength( e );
37+
}
38+
39+
<span class="keyword">void</span> ValidateNameLength( ValidatorEventArgs e )
1740
{
18-
<span class="comment">// ...</span>
41+
<span class="keyword">var</span> name = Convert.ToString( e.Value );
42+
43+
e.Status = <span class="keyword">string</span>.IsNullOrWhiteSpace( name )
44+
? ValidationStatus.Error
45+
: name.Length &lt; <span class="number">4</span>
46+
? ValidationStatus.Warning
47+
: ValidationStatus.Success;
1948
}
2049
}
2150
</pre></div>
22-
</div>
51+
</div>
Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,47 @@
1-
@namespace Blazorise.Docs.Docs.Examples
1+
@namespace Blazorise.Docs.Docs.Examples
22

3-
<Validation Validator="@ValidateCheck">
4-
<Check TValue="bool">
5-
<ChildContent>
6-
Check me out
7-
</ChildContent>
3+
<Validation Validator="@ValidateDisplayName">
4+
<TextInput Placeholder="Enter display name">
85
<Feedback>
9-
<ValidationError>You must check me out!</ValidationError>
6+
<ValidationNone>Please enter a display name.</ValidationNone>
7+
<ValidationWarning>Short display names are allowed, but longer names are easier to recognize.</ValidationWarning>
8+
<ValidationSuccess>Display name looks good.</ValidationSuccess>
9+
<ValidationError>Display name is required.</ValidationError>
1010
</Feedback>
11-
</Check>
11+
</TextInput>
12+
</Validation>
13+
14+
<Validation Validator="@ValidateUserName">
15+
<TextInput Placeholder="Enter username">
16+
<Feedback>
17+
<ValidationFeedback>
18+
<None>Please enter a username.</None>
19+
<Warning>Short usernames are allowed, but longer usernames are easier to identify.</Warning>
20+
<Success>Username looks good.</Success>
21+
<Error>Username is required.</Error>
22+
</ValidationFeedback>
23+
</Feedback>
24+
</TextInput>
1225
</Validation>
1326
@code{
14-
void ValidateCheck( ValidatorEventArgs e )
27+
void ValidateDisplayName( ValidatorEventArgs e )
1528
{
16-
// ...
29+
ValidateNameLength( e );
30+
}
31+
32+
void ValidateUserName( ValidatorEventArgs e )
33+
{
34+
ValidateNameLength( e );
35+
}
36+
37+
void ValidateNameLength( ValidatorEventArgs e )
38+
{
39+
var name = Convert.ToString( e.Value );
40+
41+
e.Status = string.IsNullOrWhiteSpace( name )
42+
? ValidationStatus.Error
43+
: name.Length < 4
44+
? ValidationStatus.Warning
45+
: ValidationStatus.Success;
1746
}
1847
}

Documentation/Blazorise.Docs/Pages/Docs/Components/Validations/ValidationPage.razor

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@
5050
<Code Tag>ValidationSuccess</Code> displays the success message.
5151
</Paragraph>
5252
</UnorderedListItem>
53+
<UnorderedListItem>
54+
<Paragraph>
55+
<Code Tag>ValidationWarning</Code> displays a non-blocking warning message.
56+
</Paragraph>
57+
</UnorderedListItem>
5358
<UnorderedListItem>
5459
<Paragraph>
5560
<Code Tag>ValidationError</Code> displays the error message.
@@ -60,6 +65,11 @@
6065
<Code Tag>ValidationNone</Code> displays a message when nothing has happened.
6166
</Paragraph>
6267
</UnorderedListItem>
68+
<UnorderedListItem>
69+
<Paragraph>
70+
<Code Tag>ValidationFeedback</Code> groups the <Code>None</Code>, <Code>Warning</Code>, <Code>Success</Code>, and <Code>Error</Code> fragments in one component.
71+
</Paragraph>
72+
</UnorderedListItem>
6373
</UnorderedList>
6474
</UnorderedListItem>
6575
</UnorderedList>
@@ -110,12 +120,20 @@
110120
</DocsPageSection>
111121

112122
<DocsPageSection>
113-
<DocsPageSectionHeader>
114-
The same structure applies to all <Code>Edit</Code> components (check, radio, select, etc.). Note that some components
115-
have special rules when defining the validation structure. For example, for <Code>Check</Code> you must use the
116-
<Code>ChildContent</Code> tag along with the <Code>Feedback</Code> tag. This is a limitation in Blazor and may be
117-
addressed in the future.
123+
<DocsPageSectionHeader Title="Warning and grouped feedback">
124+
<Paragraph>
125+
Use <Code Tag>ValidationWarning</Code> when a value is acceptable but should still show non-blocking guidance.
126+
To keep all feedback fragments together, use <Code Tag>ValidationFeedback</Code> with <Code Tag>None</Code>,
127+
<Code Tag>Warning</Code>, <Code Tag>Success</Code>, and <Code Tag>Error</Code> child fragments.
128+
</Paragraph>
129+
<Paragraph>
130+
The same feedback structure applies to all <Code>Edit</Code> components (check, radio, select, etc.). Some components
131+
have special rules when defining child content and feedback.
132+
</Paragraph>
118133
</DocsPageSectionHeader>
134+
<DocsPageSectionContent Outlined FullWidth>
135+
<ValidationFeedbackExample />
136+
</DocsPageSectionContent>
119137
<DocsPageSectionSource Code="ValidationFeedbackExample" />
120138
</DocsPageSection>
121139

@@ -316,4 +334,4 @@
316334
</DocsMethodsItem>
317335
</DocsMethods>
318336

319-
<ComponentApiDocs ComponentTypes="[typeof(Validations),typeof(Validation),typeof(ValidationError)]" />
337+
<ComponentApiDocs ComponentTypes="[typeof( Validations ), typeof( Validation ), typeof( ValidationNone ), typeof( ValidationSuccess ), typeof( ValidationWarning ), typeof( ValidationError ), typeof( ValidationFeedback )]" />

0 commit comments

Comments
 (0)