Skip to content

Commit f741541

Browse files
committed
Add more complex demo
1 parent bb3bf86 commit f741541

File tree

8 files changed

+258
-155
lines changed

8 files changed

+258
-155
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
@page "/complex-form"
2+
@rendermode InteractiveServer
3+
4+
@using System.ComponentModel.DataAnnotations
5+
@using BlazorUnitedApp.Validation
6+
7+
<PageTitle>Validated Order Form</PageTitle>
8+
9+
<h3>Validated Order Form</h3>
10+
11+
<EditForm Model="@order" OnValidSubmit="@HandleValidSubmit" OnInvalidSubmit="@HandleInvalidSubmit">
12+
<DataAnnotationsValidator />
13+
14+
<div class="container mt-4">
15+
<h4>Order Details</h4>
16+
<div class="mb-3">
17+
<label for="orderName" class="form-label">Order Name</label>
18+
<InputText id="orderName" @bind-Value="order.OrderName" class="form-control" />
19+
<ValidationMessage For="@(() => order.OrderName)" />
20+
</div>
21+
22+
<hr />
23+
24+
<h4>Customer Details</h4>
25+
<div class="card mb-3">
26+
<div class="card-body">
27+
<div class="mb-3">
28+
<label for="customerFullName" class="form-label">Full Name</label>
29+
<InputText id="customerFullName" @bind-Value="order.CustomerDetails.FullName" class="form-control" />
30+
<ValidationMessage For="@(() => order.CustomerDetails.FullName)" />
31+
</div>
32+
<div class="mb-3">
33+
<label for="customerEmail" class="form-label">Email</label>
34+
<InputText id="customerEmail" @bind-Value="order.CustomerDetails.Email" class="form-control" />
35+
<ValidationMessage For="@(() => order.CustomerDetails.Email)" />
36+
</div>
37+
<div class="mb-3">
38+
<label for="customerAge" class="form-label">Age</label>
39+
<InputNumber id="customerAge" @bind-Value="order.CustomerDetails.Age" class="form-control" />
40+
<ValidationMessage For="@(() => order.CustomerDetails.Age)" />
41+
</div>
42+
43+
<h5>Shipping Address</h5>
44+
<div class="card mb-3">
45+
<div class="card-body">
46+
<div class="mb-3">
47+
<label for="shippingStreet" class="form-label">Street</label>
48+
<InputText id="shippingStreet" @bind-Value="order.CustomerDetails.ShippingAddress.Street" class="form-control" />
49+
<ValidationMessage For="@(() => order.CustomerDetails.ShippingAddress.Street)" />
50+
</div>
51+
<div class="mb-3">
52+
<label for="shippingCity" class="form-label">City</label>
53+
<InputText id="shippingCity" @bind-Value="order.CustomerDetails.ShippingAddress.City" class="form-control" />
54+
<ValidationMessage For="@(() => order.CustomerDetails.ShippingAddress.City)" />
55+
</div>
56+
<div class="mb-3">
57+
<label for="shippingZipCode" class="form-label">Zip Code</label>
58+
<InputText id="shippingZipCode" @bind-Value="order.CustomerDetails.ShippingAddress.ZipCode" class="form-control" />
59+
<ValidationMessage For="@(() => order.CustomerDetails.ShippingAddress.ZipCode)" />
60+
</div>
61+
</div>
62+
</div>
63+
</div>
64+
</div>
65+
66+
<hr />
67+
68+
<h4>Order Items</h4>
69+
@if (order.OrderItems.Any())
70+
{
71+
for (int i = 0; i < order.OrderItems.Count; i++)
72+
{
73+
var itemIndex = i;
74+
<div class="card mb-3">
75+
<div class="card-header d-flex justify-content-between align-items-center">
76+
<span>Item @(itemIndex + 1)</span>
77+
<button type="button" class="btn btn-sm btn-danger" @onclick="() => RemoveOrderItem(itemIndex)">Remove</button>
78+
</div>
79+
<div class="card-body">
80+
<div class="mb-3">
81+
<label for="@($"productName_{itemIndex}")" class="form-label">Product Name</label>
82+
<InputText id="@($"productName_{itemIndex}")" @bind-Value="order.OrderItems[itemIndex].ProductName" class="form-control" />
83+
<ValidationMessage For="@(() => order.OrderItems[itemIndex].ProductName)" />
84+
</div>
85+
<div class="row">
86+
<div class="col-md-6 mb-3">
87+
<label for="@($"quantity_{itemIndex}")" class="form-label">Quantity</label>
88+
<InputNumber id="@($"quantity_{itemIndex}")" @bind-Value="order.OrderItems[itemIndex].Quantity" class="form-control" />
89+
<ValidationMessage For="@(() => order.OrderItems[itemIndex].Quantity)" />
90+
</div>
91+
<div class="col-md-6 mb-3">
92+
<label for="@($"price_{itemIndex}")" class="form-label">Price</label>
93+
<InputNumber id="@($"price_{itemIndex}")" @bind-Value="order.OrderItems[itemIndex].Price" class="form-control" TValue="decimal" ParseErrorMessage="Please enter a valid price." />
94+
<ValidationMessage For="@(() => order.OrderItems[itemIndex].Price)" />
95+
</div>
96+
</div>
97+
</div>
98+
</div>
99+
}
100+
}
101+
else
102+
{
103+
<p>No order items. Add one below.</p>
104+
}
105+
106+
<button type="button" class="btn btn-success mb-3" @onclick="AddOrderItem">Add Order Item</button>
107+
108+
<hr />
109+
110+
<div class="mb-3">
111+
<button type="submit" class="btn btn-primary">Submit Order</button>
112+
</div>
113+
114+
<ValidationSummary />
115+
</div>
116+
</EditForm>
117+
118+
@if (submitted)
119+
{
120+
<div class="mt-4 alert alert-success" role="alert">
121+
<h4>Form Submitted Successfully!</h4>
122+
<p>Order Name: @order.OrderName</p>
123+
<p>Customer: @order.CustomerDetails.FullName (@order.CustomerDetails.Email)</p>
124+
<h5>Order Items:</h5>
125+
<ul>
126+
@foreach (var item in order.OrderItems)
127+
{
128+
<li>@item.Quantity x @item.ProductName at @item.Price.ToString("C")</li>
129+
}
130+
</ul>
131+
</div>
132+
}
133+
134+
@if (submitFailed)
135+
{
136+
<div class="mt-4 alert alert-danger" role="alert">
137+
<h4>Form Submission Failed!</h4>
138+
<p>Please correct the validation errors and try again.</p>
139+
</div>
140+
}
141+
142+
143+
@code {
144+
private OrderModel order = new OrderModel();
145+
private bool submitted = false;
146+
private bool submitFailed = false;
147+
148+
private void HandleValidSubmit()
149+
{
150+
Console.WriteLine("Form submitted successfully!");
151+
// Here you would typically process the order
152+
// For demo purposes, we'll just display a success message
153+
submitted = true;
154+
submitFailed = false;
155+
// To see the data in console:
156+
// System.Text.Json.JsonSerializer.Serialize(order);
157+
}
158+
159+
private void HandleInvalidSubmit()
160+
{
161+
Console.WriteLine("Form submission failed due to validation errors.");
162+
submitted = false;
163+
submitFailed = true;
164+
}
165+
166+
private void AddOrderItem()
167+
{
168+
order.OrderItems.Add(new OrderItemModel());
169+
submitted = false; // Reset submission status
170+
submitFailed = false;
171+
}
172+
173+
private void RemoveOrderItem(int index)
174+
{
175+
if (index >= 0 && index < order.OrderItems.Count)
176+
{
177+
order.OrderItems.RemoveAt(index);
178+
}
179+
submitted = false; // Reset submission status
180+
submitFailed = false;
181+
}
182+
}

src/Components/Samples/BlazorUnitedApp/Pages/ValidatedForm.razor

Lines changed: 0 additions & 103 deletions
This file was deleted.

src/Components/Samples/BlazorUnitedApp/Shared/NavMenu.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
</NavLink>
1616
</div>
1717
<div class="nav-item px-3">
18-
<NavLink class="nav-link" href="validated-form">
19-
<span class="bi bi-plus-square-fill" aria-hidden="true"></span> Validated form
18+
<NavLink class="nav-link" href="complex-form">
19+
<span class="bi bi-plus-square-fill" aria-hidden="true"></span> Form validation
2020
</NavLink>
2121
</div>
2222
<div class="nav-item px-3">
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace BlazorUnitedApp.Validation;
4+
5+
public class AddressModel
6+
{
7+
[Required(ErrorMessage = "Street is required.")]
8+
public string? Street { get; set; }
9+
10+
[Required(ErrorMessage = "City is required.")]
11+
public string? City { get; set; }
12+
13+
[Required(ErrorMessage = "Zip Code is required.")]
14+
[StringLength(10, MinimumLength = 5, ErrorMessage = "Zip Code must be between 5 and 10 characters.")]
15+
public string? ZipCode { get; set; }
16+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace BlazorUnitedApp.Validation;
4+
5+
public class CustomerModel
6+
{
7+
[Required(ErrorMessage = "Full Name is required.")]
8+
public string? FullName { get; set; }
9+
10+
[Required(ErrorMessage = "Email is required.")]
11+
[EmailAddress(ErrorMessage = "Invalid Email Address.")]
12+
public string? Email { get; set; }
13+
14+
[Required(ErrorMessage = "Age is required.")]
15+
[Range(18, 99, ErrorMessage = "Age must be between 18 and 99.")]
16+
public int? Age { get; set; }
17+
18+
public AddressModel ShippingAddress { get; set; } = new AddressModel();
19+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace BlazorUnitedApp.Validation;
4+
5+
public class OrderItemModel
6+
{
7+
[Required(ErrorMessage = "Product Name is required.")]
8+
public string? ProductName { get; set; }
9+
10+
[Range(1, 100, ErrorMessage = "Quantity must be between 1 and 100.")]
11+
public int Quantity { get; set; } = 1;
12+
13+
[Range(0.01, 1000.00, ErrorMessage = "Price must be between $0.01 and $1000.00.")]
14+
[DataType(DataType.Currency)]
15+
public decimal Price { get; set; } = 0.01m;
16+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using Microsoft.AspNetCore.Http.Validation;
3+
4+
namespace BlazorUnitedApp.Validation;
5+
6+
#pragma warning disable ASP0029 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
7+
[ValidatableType]
8+
#pragma warning restore ASP0029 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
9+
public class OrderModel
10+
{
11+
[Required(ErrorMessage = "Order Name is required.")]
12+
[StringLength(100, ErrorMessage = "Order Name cannot be longer than 100 characters.")]
13+
public string? OrderName { get; set; }
14+
15+
public CustomerModel CustomerDetails { get; set; } = new CustomerModel();
16+
17+
public List<OrderItemModel> OrderItems { get; set; } = new List<OrderItemModel>();
18+
19+
public OrderModel()
20+
{
21+
OrderItems.Add(new OrderItemModel());
22+
}
23+
}

0 commit comments

Comments
 (0)