Skip to content

Commit a9a6275

Browse files
chore(grid):added custom validation in grid's editortemplate (#100)
1 parent dba9a9f commit a9a6275

33 files changed

+1633
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.31129.286
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemoteValidationInGridEditorTemplate.Server", "RemoteValidationInGridEditorTemplate\Server\RemoteValidationInGridEditorTemplate.Server.csproj", "{3BED884A-962F-49EF-8A17-A092EFE8BD3A}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemoteValidationInGridEditorTemplate.Client", "RemoteValidationInGridEditorTemplate\Client\RemoteValidationInGridEditorTemplate.Client.csproj", "{205EF599-0E53-4C81-99B4-4016AD820BA2}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemoteValidationInGridEditorTemplate.Shared", "RemoteValidationInGridEditorTemplate\Shared\RemoteValidationInGridEditorTemplate.Shared.csproj", "{CE2FDED2-666B-40D0-8C28-11DB93CD0E56}"
11+
EndProject
12+
Global
13+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
14+
Debug|Any CPU = Debug|Any CPU
15+
Release|Any CPU = Release|Any CPU
16+
EndGlobalSection
17+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
18+
{3BED884A-962F-49EF-8A17-A092EFE8BD3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19+
{3BED884A-962F-49EF-8A17-A092EFE8BD3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
20+
{3BED884A-962F-49EF-8A17-A092EFE8BD3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
21+
{3BED884A-962F-49EF-8A17-A092EFE8BD3A}.Release|Any CPU.Build.0 = Release|Any CPU
22+
{205EF599-0E53-4C81-99B4-4016AD820BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{205EF599-0E53-4C81-99B4-4016AD820BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{205EF599-0E53-4C81-99B4-4016AD820BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{205EF599-0E53-4C81-99B4-4016AD820BA2}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{CE2FDED2-666B-40D0-8C28-11DB93CD0E56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{CE2FDED2-666B-40D0-8C28-11DB93CD0E56}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{CE2FDED2-666B-40D0-8C28-11DB93CD0E56}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{CE2FDED2-666B-40D0-8C28-11DB93CD0E56}.Release|Any CPU.Build.0 = Release|Any CPU
30+
EndGlobalSection
31+
GlobalSection(SolutionProperties) = preSolution
32+
HideSolutionNode = FALSE
33+
EndGlobalSection
34+
GlobalSection(ExtensibilityGlobals) = postSolution
35+
SolutionGuid = {2708512F-644C-4167-BAC7-B105B98BFF07}
36+
EndGlobalSection
37+
EndGlobal
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Router AppAssembly="@typeof(Program).Assembly">
2+
<Found Context="routeData">
3+
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
4+
</Found>
5+
<NotFound>
6+
<LayoutView Layout="@typeof(MainLayout)">
7+
<p>Sorry, there's nothing at this address.</p>
8+
</LayoutView>
9+
</NotFound>
10+
</Router>
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
@page "/"
2+
@using System.Net
3+
@using System.Net.Http.Json
4+
@using RemoteValidationInGridEditorTemplate.Shared
5+
@inject HttpClient Http
6+
7+
Try to Update an item with an empty "Name" field.
8+
<br />
9+
Try to Update an item with the name "Nameee".
10+
<br/>
11+
This sample uses a Notification component to show the error message to supplement any data annotation validation.
12+
13+
<TelerikGrid Data=@MyData EditMode="@GridEditMode.Inline" Pageable="true" Height="300px" OnUpdate="@UpdateHandler">
14+
<GridColumns>
15+
<GridColumn Field=@nameof(SampleData.ID) Editable="false" Title="ID" />
16+
<GridColumn Field=@nameof(SampleData.Name) Title="Name">
17+
<EditorTemplate>
18+
@{
19+
CurrentlyEditedEmployee = context as SampleData;
20+
<TelerikTextBox @bind-Value="@CurrentlyEditedEmployee.Name"></TelerikTextBox>
21+
<CustomValidation @ref="customValidation" />
22+
}
23+
</EditorTemplate>
24+
</GridColumn>
25+
<GridColumn Field=@nameof(SampleData.Role) Title="Position">
26+
<EditorTemplate>
27+
@{
28+
CurrentlyEditedEmployee = context as SampleData;
29+
<select @bind="@CurrentlyEditedEmployee.Role">
30+
@foreach (var item in Roles)
31+
{
32+
<option value="@item">@item</option>
33+
}
34+
</select>
35+
}
36+
</EditorTemplate>
37+
</GridColumn>
38+
<GridCommandColumn>
39+
<GridCommandButton Command="Save" Icon="save" ShowInEdit="true">Update</GridCommandButton>
40+
<GridCommandButton Command="Edit" Icon="edit">Edit</GridCommandButton>
41+
</GridCommandColumn>
42+
</GridColumns>
43+
</TelerikGrid>
44+
<TelerikNotification @ref="@Notification"
45+
HorizontalPosition="@NotificationHorizontalPosition.Center"
46+
VerticalPosition="@NotificationVerticalPosition.Top"
47+
Class="big-notification">
48+
</TelerikNotification>
49+
50+
@code {
51+
private bool disabled;
52+
private string message;
53+
private string messageStyles = "visibility:hidden";
54+
private CustomValidation customValidation;
55+
List<SampleData> MyData { get; set; }
56+
List<string> Roles { get; set; }
57+
SampleData CurrentlyEditedEmployee { get; set; }
58+
TelerikNotification Notification { get; set; }
59+
60+
void ShowErrorNotification(string message)
61+
{
62+
Notification.Show(new NotificationModel { CloseAfter = 0, Text = message, ThemeColor = Telerik.Blazor.ThemeColors.Error });
63+
}
64+
65+
public async Task UpdateHandler(GridCommandEventArgs args)
66+
{
67+
SampleData item = (SampleData)args.Item;
68+
69+
await MyService.Update(item);
70+
71+
await GetGridData();
72+
73+
customValidation.ClearErrors();
74+
75+
var response = await Http.PostAsJsonAsync<SampleData>(
76+
"MyValidation", (SampleData)customValidation.CurrentEditContext.Model);
77+
78+
var errors = await response.Content
79+
.ReadFromJsonAsync<Dictionary<string, List<string>>>();
80+
81+
if (response.StatusCode == HttpStatusCode.BadRequest &&
82+
errors.Count() > 0)
83+
{
84+
customValidation.DisplayErrors(errors);
85+
86+
args.IsCancelled = true;
87+
88+
foreach (var error in errors)
89+
{
90+
foreach (var errorName in error.Value)
91+
{
92+
ShowErrorNotification(errorName);
93+
}
94+
}
95+
}
96+
}
97+
98+
async Task GetGridData()
99+
{
100+
MyData = await MyService.Read();
101+
Roles = await MyService.GetRoles();
102+
}
103+
104+
protected override async Task OnInitializedAsync()
105+
{
106+
await GetGridData();
107+
}
108+
109+
public static class MyService
110+
{
111+
private static List<SampleData> _data { get; set; } = new List<SampleData>();
112+
private static List<string> Roles = new List<string> { "Manager", "Employee", "Contractor" };
113+
114+
public static async Task<List<SampleData>> Read()
115+
{
116+
if (_data.Count < 1)
117+
{
118+
for (int i = 1; i < 50; i++)
119+
{
120+
_data.Add(new SampleData()
121+
{
122+
ID = i,
123+
Name = "Name " + i.ToString(),
124+
Role = Roles[i % Roles.Count]
125+
});
126+
}
127+
}
128+
129+
return await Task.FromResult(_data);
130+
}
131+
132+
public static async Task<List<string>> GetRoles()
133+
{
134+
return await Task.FromResult(Roles);
135+
}
136+
137+
public static async Task Update(SampleData itemToUpdate)
138+
{
139+
var index = _data.FindIndex(i => i.ID == itemToUpdate.ID);
140+
if (index != -1)
141+
{
142+
_data[index] = itemToUpdate;
143+
}
144+
}
145+
}
146+
}
147+
148+
<style>
149+
.big-notification .k-notification-container .k-notification-wrap {
150+
width: 330px;
151+
height: 80px;
152+
align-items: center;
153+
font-size: 26px;
154+
text-align: center;
155+
}
156+
157+
.big-notification .k-notification-container .k-notification-wrap .k-icon.k-i-error::before {
158+
font-size: 26px;
159+
}
160+
161+
.big-notification {
162+
z-index: 654321;
163+
}
164+
</style>
165+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using System;
4+
using System.Net.Http;
5+
using System.Threading.Tasks;
6+
7+
namespace RemoteValidationInGridEditorTemplate.Client
8+
{
9+
public class Program
10+
{
11+
public static async Task Main(string[] args)
12+
{
13+
var builder = WebAssemblyHostBuilder.CreateDefault(args);
14+
builder.RootComponents.Add<App>("#app");
15+
builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
16+
17+
builder.Services.AddTelerikBlazor();
18+
19+
await builder.Build().RunAsync();
20+
}
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"iisSettings": {
3+
"windowsAuthentication": false,
4+
"anonymousAuthentication": true,
5+
"iisExpress": {
6+
"applicationUrl": "http://localhost:55337/",
7+
"sslPort": 44377
8+
}
9+
},
10+
"profiles": {
11+
"IIS Express": {
12+
"commandName": "IISExpress",
13+
"launchBrowser": true,
14+
"environmentVariables": {
15+
"ASPNETCORE_ENVIRONMENT": "Development"
16+
}
17+
},
18+
"RemoteValidationInGridEditorTemplate.Client": {
19+
"commandName": "Project",
20+
"launchBrowser": true,
21+
"environmentVariables": {
22+
"ASPNETCORE_ENVIRONMENT": "Development"
23+
},
24+
"applicationUrl": "https://localhost:5001;http://localhost:5000"
25+
}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
3+
<PropertyGroup>
4+
<TargetFramework>net5.0</TargetFramework>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.0" />
8+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.0" PrivateAssets="all" />
9+
<PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
10+
<PackageReference Include="Telerik.UI.for.Blazor" Version="2.24.0" />
11+
</ItemGroup>
12+
<ItemGroup>
13+
<ProjectReference Include="..\Shared\RemoteValidationInGridEditorTemplate.Shared.csproj" />
14+
</ItemGroup>
15+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Microsoft.AspNetCore.Components;
4+
using Microsoft.AspNetCore.Components.Forms;
5+
6+
namespace RemoteValidationInGridEditorTemplate.Shared
7+
{
8+
public class CustomValidation : ComponentBase
9+
{
10+
private ValidationMessageStore messageStore;
11+
12+
[CascadingParameter]
13+
public EditContext CurrentEditContext { get; set; }
14+
15+
protected override void OnInitialized()
16+
{
17+
if (CurrentEditContext == null)
18+
{
19+
throw new InvalidOperationException(
20+
$"{nameof(CustomValidation)} requires a cascading " +
21+
$"parameter of type {nameof(EditContext)}. " +
22+
$"For example, you can use {nameof(CustomValidation)} " +
23+
$"inside an {nameof(EditForm)}.");
24+
}
25+
26+
messageStore = new(CurrentEditContext);
27+
28+
CurrentEditContext.OnValidationRequested += (s, e) =>
29+
messageStore.Clear();
30+
CurrentEditContext.OnFieldChanged += (s, e) =>
31+
messageStore.Clear(e.FieldIdentifier);
32+
}
33+
34+
public void DisplayErrors(Dictionary<string, List<string>> errors)
35+
{
36+
foreach (var err in errors)
37+
{
38+
messageStore.Add(CurrentEditContext.Field(err.Key), err.Value);
39+
}
40+
41+
CurrentEditContext.NotifyValidationStateChanged();
42+
}
43+
44+
public void ClearErrors()
45+
{
46+
messageStore.Clear();
47+
CurrentEditContext.NotifyValidationStateChanged();
48+
}
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@layout TelerikLayout
2+
3+
@inherits LayoutComponentBase
4+
5+
<div class="sidebar">
6+
<NavMenu />
7+
</div>
8+
9+
<div class="main">
10+
<div class="top-row px-4">
11+
<a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
12+
</div>
13+
14+
<div class="content px-4">
15+
@Body
16+
</div>
17+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<div class="top-row pl-4 navbar navbar-dark">
2+
<a class="navbar-brand" href="">RemoteValidationInGridEditorTemplate</a>
3+
<button class="navbar-toggler" @onclick="ToggleNavMenu">
4+
<span class="navbar-toggler-icon"></span>
5+
</button>
6+
</div>
7+
8+
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
9+
<ul class="nav flex-column">
10+
<li class="nav-item px-3">
11+
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
12+
<span class="oi oi-home" aria-hidden="true"></span> Home
13+
</NavLink>
14+
</li>
15+
</ul>
16+
</div>
17+
18+
@code {
19+
bool collapseNavMenu = true;
20+
21+
string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
22+
23+
void ToggleNavMenu()
24+
{
25+
collapseNavMenu = !collapseNavMenu;
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@inherits LayoutComponentBase
2+
3+
<TelerikRootComponent>
4+
@Body
5+
</TelerikRootComponent>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@using System.Net.Http
2+
@using Microsoft.AspNetCore.Components.Forms
3+
@using Microsoft.AspNetCore.Components.Routing
4+
@using Microsoft.AspNetCore.Components.Web
5+
@using Microsoft.JSInterop
6+
@using System.Net.Http.Json
7+
@using RemoteValidationInGridEditorTemplate.Client
8+
@using RemoteValidationInGridEditorTemplate.Client.Shared
9+
@using Telerik.Blazor
10+
@using Telerik.Blazor.Components

0 commit comments

Comments
 (0)