Blazor ValidationMessage being conditional

Kuler Master 406 Reputation points
2024-12-03T11:08:10.6566667+00:00

Hello,

I have a registration form where the users can select if they are private or company.

What I need is to make the Company Name validation conditional. Meaning, if they select a company it gets enabled and if they select a private it gets disabled.

public class Credential : ValidationAttribute 
{
    [Required(ErrorMessageResourceName = "Validation_RequiredField", ErrorMessageResourceType = typeof(Resources))]
    public int? AccountType { get; set; }
    [Required(ErrorMessageResourceName = "Validation_RequiredField", ErrorMessageResourceType = typeof(Resources))]
    public string? FirstName { get; set; }
    [Required(ErrorMessageResourceName = "Validation_RequiredField", ErrorMessageResourceType = typeof(Resources))]
    public string? LastName { get; set; }
    [Required(ErrorMessageResourceName = "Validation_RequiredField", ErrorMessageResourceType = typeof(Resources))]
    public string? CompanyName { get; set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var cred = (Credential)validationContext.ObjectInstance;
        if(cred.AccountType == 0)
        {
            //-- Disable CompanyName validation;
        }
        else
       {
           //-- Enable CompanyName validation;
       }
        return ValidationResult.Success;
    }
}

<div class="row mb-4">
    <div class="col">
        <div class="btn-group" role="group">
            @foreach (var accounttype in accounttypes)
            {
                @if (accounttypes.IndexOf(accounttype) == 0)
                {
                    <input type="radio" class="btn-check" name="acctType" id="acctType1" autocomplete="off" onchange="AccountTypeChanged('private');" checked>
                    <label class="btn btn-outline-primary" for="acctType1">@accounttype <i class="fa-solid fa-briefcase"></i></label>
                }
                else
                {
                    <input type="radio" class="btn-check" name="acctType" id="acctType2" autocomplete="off" onchange="AccountTypeChanged('company');">
                    <label class="btn btn-outline-primary" for="acctType2">@accounttype <i class="fa-solid fa-building"></i></label>
                }
            }
        </div>
    </div>
</div>

<div class="row mb-4">
    <div class="col-6">
        <div class="form-floating">
            <InputText type="text" class="form-control" id="firstname" placeholder="John" @bind-Value="@_credential.FirstName" />
            <label for="firstname"><i class="fa-solid fa-user"></i> First name</label>
            <ValidationMessage For="@(() => _credential.FirstName)" />
        </div>
    </div>
    <div class="col-6">
        <div class="form-floating">
            <InputText type="text" class="form-control" id="lastname" placeholder="Doe" @bind-Value="@_credential.LastName" />
            <label for="lastname"><i class="fa-regular fa-user"></i> Last name</label>
            <ValidationMessage For="@(() => _credential.LastName)" />
        </div>
    </div>
</div>

<div class="row mb-4 d-none" id="rowCompany">
    <div class="col">
        <div class="form-floating">
            <InputText type="text" class="form-control" id="companyname" placeholder="Foo LLC" @bind-Value="@_credential.CompanyName" />
            <label for="companyname"><i class="fa-regular fa-building"></i> Company name</label>
            <ValidationMessage For="@(() => _credential.CompanyName)" />
        </div>
    </div>
</div>

<script>
    function AccountTypeChanged(typeofaccount){
        var alert = $("#alertWarning");
        var company = $("#rowCompany");
        if (typeofaccount == 'company') {
            alert.removeClass("d-none");
            company.removeClass("d-none");
        }
        else{
            alert.addClass("d-none");
            company.addClass("d-none");
        }
    }
</script>

Thank you so much!

Developer technologies | ASP.NET | ASP.NET Core
Developer technologies | .NET | Blazor
Developer technologies | ASP.NET | Other
{count} votes

3 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 79,101 Reputation points Volunteer Moderator
    2024-12-03T16:24:45.51+00:00

    You will need to write custom validation, or pick a 3rd party validation library that supports conditional validation.

    https://learn.microsoft.com/en-us/aspnet/core/blazor/forms/validation?view=aspnetcore-9.0

    0 comments No comments

  2. Anonymous
    2024-12-24T05:36:01.05+00:00

    Hi @Kuler Master

    For conditional validation you could refer to the demo below:

    Model design and custom ValidationAttribute

    public class Credential
    {
        [Required]
        public int AccountType { get; set; } 
        [Required]
        public string? FirstName { get; set; }
        [Required]
        public string LastName { get; set; }
        [RequieredIf(Condition = "AccountType")]
        public string CompanyName { get; set; }  // Make CompanyName not required initially.
    }
    public class RequieredIfAttribute : ValidationAttribute
    {
        public string? Condition { get; set; }
        public RequieredIfAttribute()
        {
        }
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            string data = (string)value;
            int? selectedType = (int?)validationContext.ObjectType.GetProperty(Condition).GetValue(validationContext.ObjectInstance, null);
            if (string.IsNullOrEmpty(data) && selectedType != 0)
            {
                return new ValidationResult("Company Name is requiered.");
            }
            return ValidationResult.Success;
        }
    }
    

    Razor Component

    @page "/"
    @rendermode InteractiveServer
    <EditForm Model="_credential" OnValidSubmit="Submit" FormName="TestForm">
        <ValidationSummary />
        <DataAnnotationsValidator />
        <div class="row mb-4">
            <div class="col">
                <div class="btn-group" role="group">
                    <InputRadioGroup @bind-Value="@_credential.AccountType">
                        @foreach (var accounttype in accounttypes)
                        {
                            var index = accounttypes.IndexOf(accounttype);
                            <InputRadio Value="index" />
                            @accounttype
                            <br>
                        }
                    </InputRadioGroup>
                  
                </div>
            </div>
        </div>
        <div class="row mb-4">
            <div class="col-6">
                <div class="form-floating">
                    <InputText type="text" class="form-control" id="firstname" placeholder="John" @bind-Value="@_credential.FirstName" />
                    <label for="firstname"><i class="fa-solid fa-user"></i> First name</label>
                    <ValidationMessage For="@(() => _credential.FirstName)" />
                </div>
            </div>
            <div class="col-6">
                <div class="form-floating">
                    <InputText type="text" class="form-control" id="lastname" placeholder="Doe" @bind-Value="@_credential.LastName" />
                    <label for="lastname"><i class="fa-regular fa-user"></i> Last name</label>
                    <ValidationMessage For="@(() => _credential.LastName)" />
                </div>
            </div>
        </div>
        <div class="row mb-4" id="rowCompany">
            <div class="col">
                <div class="form-floating">
                    <InputText type="text" class="form-control" id="companyname" placeholder="Foo LLC" @bind-Value="@_credential.CompanyName" />
                    <label for="companyname"><i class="fa-regular fa-building"></i> Company name</label>
                    <ValidationMessage For="@(() => _credential.CompanyName)" />
                </div>
            </div>
        </div>
        <button type="submit">Submit</button>
    </EditForm>
    @code {
        private EditContext? editContext;
        private List<string> accounttypes = new List<string> { "Private", "Company" };
        private Credential _credential { get; set; } = new();
        private void Submit(){
            
        }
    }
    

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Rena

    0 comments No comments

  3. Raymond Huynh (WICLOUD CORPORATION) 620 Reputation points Microsoft External Staff
    2025-07-15T08:29:33.18+00:00

    Hello @Kuler Master ,

    Thanks for sharing your code! Here’s how you can make the Company Name validation conditional in a way that’s clean and works well with Blazor.

    About your codes:

    • You’re putting validation logic inside your model class by inheriting from ValidationAttribute.
    • This isn’t the right way, your model should just be a data container, and validation attributes should be separate.
    • The [Required] attribute on CompanyName makes it always required, which isn’t what you want.

    How to Fix It :

    1. Remove the [Required] from CompanyName.
    2. Create a custom validation attribute (like RequiredIf) that only requires CompanyName if AccountType is "company".
    3. Apply that attribute to CompanyName.

    #Here’s How You Do It:

    1. Custom Attribute

    public class RequiredIfCompanyAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var cred = (Credential)validationContext.ObjectInstance;
            // Let's say AccountType == 1 means "Company"
            if (cred.AccountType == 1 && string.IsNullOrWhiteSpace(value as string))
            {
                return new ValidationResult("Company Name is required when Account Type is Company.");
            }
            return ValidationResult.Success;
        }
    }
    

    2. Update Your Model

    public class Credential
    {
        [Required(ErrorMessageResourceName = "Validation_RequiredField", ErrorMessageResourceType = typeof(Resources))]
        public int? AccountType { get; set; }
     
        [Required(ErrorMessageResourceName = "Validation_RequiredField", ErrorMessageResourceType = typeof(Resources))]
        public string? FirstName { get; set; }
     
        [Required(ErrorMessageResourceName = "Validation_RequiredField", ErrorMessageResourceType = typeof(Resources))]
        public string? LastName { get; set; }
     
        [RequiredIfCompany]
        public string? CompanyName { get; set; }
    }
    

    3. Your Blazor Form

    Your form markup is fine! The validation will now work as you want:

    • If "Company" is selected, "Company Name" must be filled in.
    • If "Private" is selected, "Company Name" can be left blank.

    Hope this helps!


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.