11

so I am creating this little project in ASP.NET Core, I've got a WEB API, already written but I am struggling with Frontend in Blazor to consume that API. POST, GET HTTP requests work great. I've got this one razor page in which I put some data in (Name, FamilyName etc.) and then I click Send, the data is POSTed to the API.

There is some validation when it comes to that form: Name – at least 5 Characters FamilyName – at least 5 Characters Adress – at least 10 Characters EmailAdress – must be an valid email Age – must be between 20 and 60

and that is all done here with DataAnnotations:

using System.ComponentModel.DataAnnotations;

namespace Blazor.Data
{
    public class Applicant
    {
        public int Id { get; set; }

        [MinLength(5, ErrorMessage ="Name must contain atleast 5 characters.")]
        public string Name { get; set; }

        [MinLength(5, ErrorMessage ="Family Name must contain atleast 5 characters.")]
        public string FamilyName { get; set; }

        [MinLength(10,ErrorMessage ="Address must contain atleast 10 characters.")]
        public string Address { get; set; }

        public string CountryOfOrigin { get; set; }

        [EmailAddress(ErrorMessage ="E-Mail adress is not valid.")]
        public string EmailAddress { get; set; }

        [Range(20,60,ErrorMessage ="Age must be between 20 and 60.")]
        public int Age { get; set; }

        public bool Hired { get; set; }
    }
}

In the Razor page I've got a form to fill out and then send to the API as follows:

@page "/postapplicant"
@using Blazor.Data
@using System.Web
@inherits ApplicantCreateBase

<h1>Create an Applicant</h1>

<p>This component demonstrates posting a data to a Web API.</p>

<EditForm Model="@Applicant" OnValidSubmit="@SendValid">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <hr />
    <div class="form-group row">
        <label for="Name" class="col-sm-2 col-form-label">
            First Name
        </label>
        <div class="col-sm-10">
            <InputText id="Name" class="form-control" placeholder="First Name"
                       @bind-Value="Applicant.Name" />
            <ValidationMessage For="@(() =>Applicant.Name)" />
        </div>
    </div>
    <div class="form-group row">
        <label for="FamilyName" class="col-sm-2 col-form-label">
            Family Name
        </label>
        <div class="col-sm-10">
            <InputText id="FamilyName" class="form-control" placeholder="Family Name"
                       @bind-Value="Applicant.FamilyName" />
            <ValidationMessage For="@(() =>Applicant.FamilyName)" />
        </div>
    </div>
    <div class="form-group row">
        <label for="Address" class="col-sm-2 col-form-label">
            Address
        </label>
        <div class="col-sm-10">
            <InputText id="Address" class="form-control" placeholder="Address"
                       @bind-Value="Applicant.Address" />
            <ValidationMessage For="@(() =>Applicant.Address)" />
        </div>
    </div>
    <div class="form-group row">
        <label for="CountryOfOrigin" class="col-sm-2 col-form-label">
            Country
        </label>
        <div class="col-sm-10">
            <InputSelect id="CountryOfOrigin" class="form-group" placeholder="Country Of Origin"
                         @bind-Value="Applicant.CountryOfOrigin">
                @foreach (var item in Countries)
                {
                    <option>@item.Title</option>
                }
            </InputSelect>
        </div>
    </div>
    <div class="form-group row">
        <label for="EMailAddress" class="col-sm-2 col-form-label">
            E-Mail Address
        </label>
        <div class="col-sm-10">
            <InputText id="EMailAddress" class="form-control" placeholder="E-Mail Address"
                       @bind-Value="Applicant.EmailAddress" />
            <ValidationMessage For="@(() =>Applicant.EmailAddress)" />
        </div>
    </div>
    <div class="form-group row">
        <label for="Age" class="col-sm-2 col-form-label">
            Age
        </label>
        <div class="col-sm-10">
            <InputNumber id="Age" class="form-control" placeholder="Age"
                         @bind-Value="Applicant.Age" />
            <ValidationMessage For="@(() =>Applicant.Age)" />
        </div>
    </div>
    <div class="form-group row">
        <label for="Hired" class="col-sm-2 col-form-label">
            Hired
        </label>
        <div class="col-md-1">
            <InputCheckbox id="Hired" class="form-control" placeholder="Hired"
                           @bind-Value="Applicant.Hired" />
        </div>
    </div>
    <button class="btn btn-primary"  type="submit">Send</button>
    <button class="btn btn-secondary" type="button" @onclick="Reset_Click">Reset</button>

</EditForm>
<Confirm ConfirmationChanged="ConfirmReset_Click" @ref="ResetConfirmation"></Confirm>

Everything works fine and as intended but I want the send button to be enabled only if the whole form is valid according to the rules I have listed above. I know there is this disabled property you can use within a button but I have no idea how to implement this correctly. It seems like such a mess in C# / .net core. Writing a web api from scratch is easier. Help would be appreciated, thank you!

2 Answers 2

21

You can access the EditForm's context:

  <button class="btn btn-primary" type="submit" disabled="@(!context.Validate())">Send</button>
2
  • 3
    This won't cause the button to be enabled as soon as the form becomes valid. For that you will have to keep track of form validity in code and bind disabled attribute to a bool and then switch the bool as soon as the form turns valid. then do StateHasChanged(). Please correct me if I am wrong.
    – DevPro1993
    Commented Nov 16, 2020 at 6:36
  • 8
    Thanks, works well! I include IsModified too, so if the form is invalid OR not modified yet, the submit is disabled: disabled="@(!context.Validate() || !context.IsModified())" Commented Jan 3, 2021 at 18:26
8

In order to avoid showing validation error message when the form is not yet modified (i.e. initially), you can use:

Disabled="@(!context.IsModified() || !context.Validate())"

Not the answer you're looking for? Browse other questions tagged or ask your own question.