Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions 10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ namespace BlazorSample;

public class CustomFieldClassProvider : FieldCssClassProvider
{
public override string GetFieldCssClass(
EditContext editContext, in FieldIdentifier fieldIdentifier) =>
editContext.IsValid(fieldIdentifier) ? "validField" : "invalidField";
public override string GetFieldCssClass(EditContext editContext,
in FieldIdentifier fieldIdentifier)
{
var isValid = editContext.IsValid(fieldIdentifier);

return isValid ? "validField" : "invalidField";
}
}
5 changes: 3 additions & 2 deletions 10.0/BlazorSample_BlazorWebApp/CustomFieldClassProvider2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ public override string GetFieldCssClass(EditContext editContext,
{
if (fieldIdentifier.FieldName == "Name")
{
return editContext.IsValid(fieldIdentifier) ?
"validField" : "invalidField";
var isValid = editContext.IsValid(fieldIdentifier);

return isValid ? "validField" : "invalidField";
}

return string.Empty;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;

namespace BlazorSample.Client;

public class CustomValidation : ComponentBase
{
private ValidationMessageStore? messageStore;

[CascadingParameter]
private EditContext? CurrentEditContext { get; set; }

protected override void OnInitialized()
{
if (CurrentEditContext is null)
{
throw new InvalidOperationException(
$"{nameof(CustomValidation)} requires a cascading " +
$"parameter of type {nameof(EditContext)}. " +
$"For example, you can use {nameof(CustomValidation)} " +
$"inside an {nameof(EditForm)}.");
}

messageStore = new(CurrentEditContext);

CurrentEditContext.OnValidationRequested += (s, e) =>
messageStore?.Clear();
CurrentEditContext.OnFieldChanged += (s, e) =>
messageStore?.Clear(e.FieldIdentifier);
}

public void DisplayErrors(IDictionary<string, string[]> errors)
{
if (CurrentEditContext is not null)
{
foreach (var err in errors)
{
messageStore?.Add(CurrentEditContext.Field(err.Key), err.Value);
}

CurrentEditContext.NotifyValidationStateChanged();
}
}

public void ClearErrors()
{
messageStore?.Clear();
CurrentEditContext?.NotifyValidationStateChanged();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
@page "/starship-10"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using BlazorSample.Client.Starship
@attribute [Authorize]
@inject IFormValidation FormValidation
@inject ILogger<Starship10> Logger

<h1>Starfleet Starship Database</h1>

<h2>New Ship Entry Form</h2>

<EditForm FormName="Starship10" Model="Model" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<CustomValidation @ref="customValidation" />
<ValidationSummary />
<div>
<label>
Identifier:
<InputText @bind-Value="Model!.Id" disabled="@disabled" />
</label>
</div>
<div>
<label>
Description (optional):
<InputTextArea @bind-Value="Model!.Description"
disabled="@disabled" />
</label>
</div>
<div>
<label>
Primary Classification:
<InputSelect @bind-Value="Model!.Classification" disabled="@disabled">
<option value="">Select classification ...</option>
<option value="Exploration">Exploration</option>
<option value="Diplomacy">Diplomacy</option>
<option value="Defense">Defense</option>
</InputSelect>
</label>
</div>
<div>
<label>
Maximum Accommodation:
<InputNumber @bind-Value="Model!.MaximumAccommodation"
disabled="@disabled" />
</label>
</div>
<div>
<label>
Engineering Approval:
<InputCheckbox @bind-Value="Model!.IsValidatedDesign"
disabled="@disabled" />
</label>
</div>
<div>
<label>
Production Date:
<InputDate @bind-Value="Model!.ProductionDate" disabled="@disabled" />
</label>
</div>
<div>
<button type="submit" disabled="@disabled">Submit</button>
</div>
<div style="@messageStyles">
@message
</div>
</EditForm>

@code {
private CustomValidation? customValidation;
private bool disabled;
private string? message;
private string messageStyles = "visibility:hidden";

[SupplyParameterFromForm]
private StarshipModel? Model { get; set; }

protected override void OnInitialized() =>
Model ??= new() { ProductionDate = DateTime.UtcNow };

private async Task Submit(EditContext editContext)
{
customValidation?.ClearErrors();

try
{
var validationProblemDetails =
await FormValidation.ValidateStarshipFormAsync(
(StarshipModel)editContext.Model);

if (validationProblemDetails?.Count > 0)
{
customValidation?.DisplayErrors(validationProblemDetails);
}
else
{
disabled = true;
messageStyles = "color:green";
message = "The form has been processed.";
}
}
catch (AccessTokenNotAvailableException ex)
{
ex.Redirect();
}
catch (Exception ex)
{
Logger.LogError(ex, "Form processing error.");
disabled = true;
messageStyles = "color:red";
message = "There was an error processing the form.";
}
}
}
12 changes: 12 additions & 0 deletions 10.0/BlazorWebAppRemoteValidation/BlazorSample.Client/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using BlazorSample.Client.Starship;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var builder = WebAssemblyHostBuilder.CreateDefault(args);

// The .Client project registers an HttpClient for HTTP POST requests to the Minimal API.
builder.Services.AddHttpClient<IFormValidation, ClientFormValidation>(httpClient =>
{
httpClient.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
});

await builder.Build().RunAsync();
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Net.Http.Json;

namespace BlazorSample.Client.Starship;

internal sealed class ClientFormValidation(HttpClient httpClient) : IFormValidation
{
public async Task<IDictionary<string, string[]>> ValidateStarshipFormAsync(
StarshipModel starship)
{
Dictionary<string, string[]> genericError = new()
{
{
"Validation Error",
["An unexpected client error occurred during validation."]
}
};

try
{
using var response = await httpClient.PostAsJsonAsync(
"/starship-validation", starship);

if (response.IsSuccessStatusCode)
{
var deserializedResponseContent =
await response.Content.ReadFromJsonAsync
<IDictionary<string, string[]>>();

return deserializedResponseContent ?? genericError;
}
}
catch (Exception)
{
// Log the exception
}

return genericError;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace BlazorSample.Client.Starship;

public interface IFormValidation
{
Task<IDictionary<string, string[]>> ValidateStarshipFormAsync(
StarshipModel starship);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.ComponentModel.DataAnnotations;

namespace BlazorSample.Client.Starship;

public class StarshipModel
{
[Required]
[StringLength(16, ErrorMessage = "Identifier too long (16 character limit).")]
public string? Id { get; set; }

public string? Description { get; set; }

[Required]
public string? Classification { get; set; }

[Range(1, 100000, ErrorMessage = "Accommodation invalid (1-100000).")]
public int MaximumAccommodation { get; set; }

[Required]
[Range(typeof(bool), "true", "true", ErrorMessage = "Approval required.")]
public bool IsValidatedDesign { get; set; }

[Required]
public DateTime ProductionDate { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using BlazorSample.Client
@using BlazorSample.Client.Starship
17 changes: 17 additions & 0 deletions 10.0/BlazorWebAppRemoteValidation/BlazorSample/BlazorSample.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\BlazorSample.Client\BlazorSample.Client.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<HeadOutlet @rendermode="InteractiveAuto" />
</head>

<body>
<Routes @rendermode="InteractiveAuto" />
<script src="_framework/blazor.web.js"></script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@inherits LayoutComponentBase

<main>
@Body
</main>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Router AppAssembly="typeof(Program).Assembly"
AdditionalAssemblies="new[] { typeof(BlazorSample.Client._Imports).Assembly }">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@using System.Net.Http
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using BlazorSample
@using BlazorSample.Components
@using BlazorSample.Components.Layout
Loading
Loading