Posts Blazor form and validation
Post
Cancel

Blazor form and validation

Checkout.razor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@page "/checkout"
@inject OrderState OrderState
@inject HttpClient HttpClient
@inject NavigationManager NavigationManager

<div class="main">
    <EditForm Model="@OrderState.Order.DeliveryAddress" OnValidSubmit="@PlaceOrder">
        <div class="checkout-cols">
            <div class="checkout-order-details">
                <h4>Review order</h4>
                <OrderReview Order="@OrderState.Order" />
            </div>

            <div class="checkout-delivery-address">
                <h4>Deliver to...</h4>
                <AddressEditor Address="@OrderState.Order.DeliveryAddress" />
            </div>
        </div>

        <button type="submit" class="checkout-button btn btn-warning">
            Place order
        </button>

        <DataAnnotationsValidator />
    </EditForm>
</div>

@code {
    async Task PlaceOrder()
    {
        var newOrderId = await HttpClient.PostJsonAsync<int>("orders", OrderState.Order);
        OrderState.ResetOrder();
        NavigationManager.NavigateTo($"myorders/{newOrderId}");
    }
}

Code explained:

  1. The EditForm component represents a form.
  2. It is bound to the OrderState.Order.DeliveryAddress of Address type.
  3. This form has 2 child components: OrderReview and AddressEditor
  4. The PlaceOrder method is assigned to OnValidSubmit.
  5. The data annotations validator (DataAnnotationsValidator component†) attaches validation support using data annotations.
  6. To handle form submission, this form uses the OnValidSubmit to assign the PlaceOrder event handler to run when the form with valid fields is submitted.
  7. The PlaceOrder event handler calls the Orders controller. Notice the Route(“orders”) and PlaceOrder action method returns an integer.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     [Route("orders")]
     [ApiController]
     // [Authorize]
     public class OrdersController : Controller
     ...
         [HttpPost]
         public async Task<ActionResult<int>> PlaceOrder(Order order)
         {
             ....
             return order.OrderId;
         }
    

AddressEditor.razor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<div class="form-field">
    <label>Name:</label>
    <div>
        <InputText @bind-Value="Address.Name" />
        <ValidationMessage For="@(() => Address.Name)" />
    </div>
</div>

<div class="form-field">
    <label>Line 1:</label>
    <div>
        <InputText @bind-Value="Address.Line1" />
        <ValidationMessage For="@(() => Address.Line1)" />
    </div>
</div>

<div class="form-field">
    <label>Line 2:</label>
    <div>
        <InputText @bind-Value="Address.Line2" />
        <ValidationMessage For="@(() => Address.Line2)" />
    </div>
</div>

<div class="form-field">
    <label>City:</label>
    <div>
        <InputText @bind-Value="Address.City" />
        <ValidationMessage For="@(() => Address.City)" />
    </div>
</div>

<div class="form-field">
    <label>Region:</label>
    <div>
        <InputText @bind-Value="Address.Region" />
        <ValidationMessage For="@(() => Address.Region)" />
    </div>
</div>

<div class="form-field">
    <label>Postal code:</label>
    <div>
        <InputText @bind-Value="Address.PostalCode" />
        <ValidationMessage For="@(() => Address.PostalCode)" />
    </div>
</div>

@code {
    [Parameter] public Address Address { get; set; }
}

Code explained

  1. The InputText component is an input component for editing string values. The @bind-Value directive attribute binds the Address.Name model property to the InputText component’s Value property.
  2. This component has a component parameter which is used to pass data from the parent component to this component and is defined using public C# properties on the component class with the [Parameter] attribute
This post is licensed under CC BY 4.0 by the author.