Input Validation

The UI for Blazor suite supports and integrates seamlessly into Blazor's Forms and Validation infrastructure. All Telerik UI for Blazor Input components work out of the box when placed inside an EditForm, respond to EditContext changes and provide default invalid styles.

To validate the Blazor inputs, you need to:

  1. Define a model that has the desired Data Annotation attributes.
  2. Place the inputs corresponding to its fields in an EditForm.
  3. Add a DataAnnotationsValidator inside the editable form.
  4. Provide the values to the inputs through the bind-Value binding syntax.

This article provides examples of validating the Telerik Blazor components. The examples are separated by input types for brevity:

Simple Inputs

Simple textbox-like inputs do not have any special behavior. You need to bind them to a model field that has the desired data annotation attributes set. Such inputs are the textbox, numeric textbox and date input.

How to validate inputs

@using System.ComponentModel.DataAnnotations
@* This Using is for the model class attributes only *@
@* The Id parameters are not mandatory for validation, they just show better forms integration *@

<EditForm Model="@person" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <p class="name">
        <label for="nameTextbox">Name:</label>
        <TelerikTextBox @bind-Value="@person.Name" Id="nameTextbox"></TelerikTextBox>
        <ValidationMessage For="@(() => person.Name)"></ValidationMessage>
    </p>
    <p class="role">
        <label for="roleAutoComplete">Role:</label>
        <TelerikAutoComplete Data="@RoleSuggestions" @bind-Value="@person.Role" Id="roleAutoComplete"
                             Placeholder="Enter your role (can be free text)" ClearButton="true" />
        <ValidationMessage For="@(() => person.Role)"></ValidationMessage>
    </p>
    <p class="height">
        <label for="heightNumeric">Height (cm):</label>
        <TelerikNumericTextBox @bind-Value="@person.Height" Id="heightNumeric" />
        <ValidationMessage For="@(() => person.Height)"></ValidationMessage>
    </p>
    <p class="birthday">
        <label for="birthdayDateInput">Birthday:</label>
        <TelerikDateInput @bind-Value="@person.Birthday" Format="dd MMMM yyyy" Id="birthdayDateInput"></TelerikDateInput>
        <ValidationMessage For="@(() => person.Birthday)"></ValidationMessage>
    </p>
    <p class="favorite-day">
        <label for="favDayDatePicker">Favorite date:</label>
        <TelerikDatePicker @bind-Value="@person.FavoriteDay" Format="dd MMMM yyyy" Id="favDayDatePicker"></TelerikDatePicker>
        <ValidationMessage For="@(() => person.FavoriteDay)"></ValidationMessage>
    </p>
    <p class="daily-scrum">
        <label for="scrumTimePicker">Daily scrum:</label>
        <TelerikTimePicker @bind-Value="@person.DailyScrum" Id="scrumTimePicker"></TelerikTimePicker>
        <ValidationMessage For="@(() => person.DailyScrum)"></ValidationMessage>
    </p>
    <p class="start-time">
        <label for="dayStartDateTimePicker">Start time:</label>
        <TelerikDateTimePicker Format="G" @bind-Value="@person.StartTime" Width="250px" Id="dayStartDateTimePicker"></TelerikDateTimePicker>
        <ValidationMessage For="@(() => person.StartTime)"></ValidationMessage>
    </p>
    <p class="accepts-terms">
        <label class="k-checkbox-label" for="acceptTermsCheckbox">Accepts terms</label>
        <TelerikCheckBox @bind-Value="@person.AcceptsTerms" Id="acceptTermsCheckbox"></TelerikCheckBox>
        <ValidationMessage For="@(() => person.AcceptsTerms)"></ValidationMessage>
    </p>

    <TelerikButton ButtonType="@ButtonType.Submit">Submit</TelerikButton>
</EditForm>

@code {
    // Usually this class would be in a different file
    public class Person
    {
        [Required(ErrorMessage = "Enter a name")]
        [StringLength(10, ErrorMessage = "That name is too long")]
        public string Name { get; set; }

        [Required]
        [StringLength(15, ErrorMessage = "That role name is too long, use abbreviations")]
        public string Role { get; set; }

        [Required(ErrorMessage = "Provide your height in centimeters")]
        [Range(1, 300, ErrorMessage = "Nobody is that tall")]
        public int? Height { get; set; }

        [Required]
        [Range(typeof(DateTime), "1/1/1900", "1/12/2000",
            ErrorMessage = "Value for {0} must be between {1:dd MMM yyyy} and {2:dd MMM yyyy}")]
        public DateTime Birthday { get; set; }

        [Required]
        [Range(typeof(DateTime), "1/1/1999", "1/12/2019",
            ErrorMessage = "Value for {0} must be between {1:dd MMM yyyy} and {2:dd MMM yyyy}")]
        [Display(Name = "Your Favourite Day")]
        public DateTime FavoriteDay { get; set; }

        [Required(ErrorMessage = "The daily standup is required")]
        [Range(typeof(DateTime), "1/1/1900 08:00:00", "1/1/1900 17:00:00",
            ErrorMessage = "Time should be in business hours, between 8AM and 5 PM.")]
        public DateTime? DailyScrum { get; set; }

        [Required(ErrorMessage = "Enter a starting time")]
        [Range(typeof(DateTime), "29/11/2018 10:00:00", "22/12/2025 17:00:00",
            ErrorMessage = "Value for {0} must be between {1:dd MMM yyyy HH:mm} and {2:dd MMM yyyy HH:mm}")]
        public DateTime StartTime { get; set; }

        [Required]
        [Range(typeof(bool), "true", "true", ErrorMessage = "Must accept terms")]
        public bool AcceptsTerms { get; set; }
    }

    Person person = new Person()
    {
        // for time pickers, the initial date value must match the date portion of the range validation rule
        DailyScrum = new DateTime(1900, 1, 1, 1, 1, 1),
    };

    void HandleValidSubmit()
    {
        Console.WriteLine("OnValidSubmit");
    }

    List<string> RoleSuggestions { get; set; } = new List<string> {
        "Manager", "Developer", "QA", "Technical Writer", "Support Engineer", "Sales Agent", "Architect", "Designer"
    };
}

The DropDownList always has an item selected - the first item from its data source, the item corresponding to the Value, or the item created from the DefaultText the developer provides (which has the default value for the type of the Value field - for example, 0 for an int and null for an int? or string).

This means that for required field validation to work, the current item must have a null value. Alternatively, if you cannot alter the dropdownlist item model you already have, you can use range validation and set a value for the default item that is outside of the range of actual values.

How to validate a dropdownlist

@using System.ComponentModel.DataAnnotations
@* This Using is for the model class attributes only *@
@* The Id parameter is not mandatory for validation, ut just shows better forms integration *@

<EditForm Model="@person" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <p class="gender">
        <label for="genderDropdownlist">Gender:</label>
        <TelerikDropDownList @bind-Value="person.Gender" DefaultText="Select gender" Id="genderDropdownlist"
                             Data="@genders" TextField="MyTextField" ValueField="MyValueField">
        </TelerikDropDownList>
        <ValidationMessage For="@(() => person.Gender)"></ValidationMessage>
    </p>

    <TelerikButton ButtonType="@ButtonType.Submit">Submit</TelerikButton>
</EditForm>

@code {
    // Usually the model classes would be in different files
    public class Person
    {
        [Required(ErrorMessage = "Gender is mandatory.")]//the value field in the dropdown model must be null in the default item
        [Range(1, 3, ErrorMessage = "Please select your gender.")] //limits the fourth option just to showcase this is honored
        public int? Gender { get; set; }
    }

    public class MyDdlModel
    {
        //nullable so the default item can allow required field validation
        //alternatively, use a range validator and put a value out of that range for the default item
        public int? MyValueField { get; set; }
        public string MyTextField { get; set; }
    }

    Person person = new Person();

    IEnumerable<MyDdlModel> genders = new List<MyDdlModel>
    {
        new MyDdlModel {MyTextField = "female", MyValueField = 1},
        new MyDdlModel {MyTextField = "male", MyValueField = 2},
        new MyDdlModel {MyTextField = "other", MyValueField = 3},
        new MyDdlModel {MyTextField = "I'd rather not say", MyValueField = 4}
    };

    void HandleValidSubmit()
    {
        Console.WriteLine("OnValidSubmit");
    }
}

ComboBox

The ComboBox works with the Value of the selected item (through its ValueField). This means that for required field validation to work, the current item must have a null value, or AllowCustom must be true and the input empty.

How to validate a combobox without custom values

@using System.ComponentModel.DataAnnotations
@* This Using is for the model class attributes only *@
@* The Id parameter is not mandatory for validation, ut just shows better forms integration *@

<EditForm Model="@person" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <p class="team">
        <label for="teamCombobox">Team:</label>
        <TelerikComboBox @bind-Value="person.Team" Placeholder="Select team" ClearButton="true" Id="teamCombobox"
                               Data="@teams" TextField="MyTextField" ValueField="MyValueField">
        </TelerikComboBox>
        <ValidationMessage For="@(() => person.Team)"></ValidationMessage>
    </p>

    <TelerikButton ButtonType="@ButtonType.Submit">Submit</TelerikButton>
</EditForm>

@code {
    // Usually the model classes would be in different files
    public class Person
    {
        [Required(ErrorMessage = "Team is mandatory.")]//the value field in the combobox model must be null for this to have effect
        [Range(1, 3, ErrorMessage = "Please select an actual team.")] //limits the fourth option just to showcase this is honored
        public int? Team { get; set; }
    }

    public class MyDdlModel
    {
        //nullable so the default item can allow required field validation
        //alternatively, use a range validator and put a value out of that range for the default item
        public int? MyValueField { get; set; }
        public string MyTextField { get; set; }
    }

    Person person = new Person();

    IEnumerable<MyDdlModel> teams = new List<MyDdlModel>
    {
        new MyDdlModel {MyTextField = "Team 1", MyValueField = 1},
        new MyDdlModel {MyTextField = "Team 2", MyValueField = 2},
        new MyDdlModel {MyTextField = "Team 3", MyValueField = 3},
        new MyDdlModel {MyTextField = "CEO", MyValueField = 4}
    };

    void HandleValidSubmit()
    {
        Console.WriteLine("OnValidSubmit");
    }
}

How to validate a combobox with custom values

@using System.ComponentModel.DataAnnotations
@* This Using is for the model class attributes only *@
@* The Id parameter is not mandatory for validation, ut just shows better forms integration *@

@*You can still use a full model, primitive types are used for brevity here*@

<EditForm Model="@person" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <p class="team">
        <label for="teamComboBox">Team:</label>
        <TelerikComboBox Data="@ExistingTeams" @bind-Value="person.Team" AllowCustom="true" ClearButton="true" Id="teamComboBox"></TelerikComboBox>
        <ValidationMessage For="@(() => person.Team)"></ValidationMessage>
    </p>

    <TelerikButton ButtonType="@ButtonType.Submit">Submit</TelerikButton>
</EditForm>

@code {
    // Usually the model classes would be in different files
    public class Person
    {
        [Required(ErrorMessage = "Team is mandatory.")]//the combo must be empty for this to take effect
        [RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$",
         ErrorMessage = "Characters are not allowed.")] // Allow up to 40 uppercase and lowercase symbols, no special characters
                                                        // Applies to custom values as well as values from the data source.
        public string Team { get; set; }
    }

    Person person = new Person();

    protected List<string> ExistingTeams = new List<string>() { "first", "second", "third" };

    void HandleValidSubmit()
    {
        Console.WriteLine("OnValidSubmit");
    }
}

MultiSelect

The MultiSelect has a value that is a List and the validation attributes must take that into account (for example, a regular expression attribute cannot work).

How to validated a MultiSelect

@using System.ComponentModel.DataAnnotations
@* This Using is for the model class attributes only *@
@* The Id parameter is not mandatory for validation, ut just shows better forms integration *@

<EditForm Model="@person" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <p class="languages">
        <label for="languagesMultiSelect">Languages:</label>
        <TelerikMultiSelect @bind-Value="@person.DevLanguages"
                                       Placeholder="Programming languages you know"
                                       Data="@DevSkills"
                                       Id="languagesMultiSelect"/>
        <ValidationMessage For="@(() => person.DevLanguages)"></ValidationMessage>
    </p>

    <TelerikButton ButtonType="@ButtonType.Submit">Submit</TelerikButton>
</EditForm>

@code {
    public class Person
    {
        [Required(ErrorMessage = "You must list the dev skills you have")]
        [MinLength(3, ErrorMessage = "At least three languages are required so this application is considered")]
        public List<string> DevLanguages { get; set; }
    }

    Person person = new Person();

    List<string> DevSkills = new List<string>
{
        "Blazor", "C#", "Python", "C", "C++", "Assembler", "Ruby", "Java", "JavaScript", "HTML", "CSS", "SQL", "PHP"
    };

    void HandleValidSubmit()
    {
        Console.WriteLine("OnValidSubmit");
    }
}

DateRangePicker

The Date Range Picker component consists of two inputs that the user can change independently. They can choose to alter one or both, and the application cannot know their intent - they can change one to an invalid value (for example, a start date that is after the end date), but then intend to change the second input as well.

There is no built-in provision in the framework for validating a field value based on another field value and so you need to implement a custom data annotation attribute to ensure the start date is before the end date.

Validate that the start date is before the end date through a custom attribute

@* These using statements are for the custom data annotation validation attribute. Check its implementation at the end of this code snippet *@
@using System.Reflection
@using System.ComponentModel.DataAnnotations

<EditForm Model="@dateRange" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <p>Try typing a date in the End input that is earlier than the Start date, and press Submit.
    Or, use the Up and Down arrows to change the value of either input.</p>
    <TelerikDateRangePicker @bind-StartValue="@dateRange.StartDate"
                            @bind-EndValue="@dateRange.EndDate" />

    <TelerikButton Class="mt-4" ButtonType="@ButtonType.Submit">Submit</TelerikButton>
</EditForm>

@code {
    private DateRangeModel dateRange { get; set; } = new DateRangeModel()
    {
        StartDate = DateTime.Today,
        EndDate = DateTime.Today.AddDays(5)
    };

    async void HandleValidSubmit()
    {
        Console.WriteLine("OnValidSubmit");
    }

    // A custom validation attribute is used to show an error message to the user
    // if they type an end date that is before the start date in the input
    public class CompareDateAttribute : ValidationAttribute
    {
        public string compareToDateTimeProperty;

        public CompareDateAttribute(string compareToPropertyName)
        {
            this.compareToDateTimeProperty = compareToPropertyName;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var validationObject = validationContext.ObjectInstance;
            PropertyInfo propertyInfo = validationObject.GetType().GetProperty(compareToDateTimeProperty);

            var currentValue = (DateTime?)value;
            var compareToValue = (DateTime?)propertyInfo?.GetValue(validationObject);

            return currentValue < compareToValue ? ValidationResult.Success : new ValidationResult(ErrorMessage);
        }
    }

    public class DateRangeModel
    {
        [Required]
        [Range(typeof(DateTime), "1/1/2019", "1/12/2025",
        ErrorMessage = "Value for {0} must be between {1:dd MMM yyyy} and {2:dd MMM yyyy}")]
        // custom validation attribute to ensure start date is before the end date
        [CompareDate(nameof(EndDate), ErrorMessage = "The Start date must be before the End date.")]
        public DateTime? StartDate { get; set; }

        [Required]
        [Range(typeof(DateTime), "1/1/2019", "1/12/2025",
        ErrorMessage = "Value for {0} must be between {1:dd MMM yyyy} and {2:dd MMM yyyy}")]
        public DateTime? EndDate { get; set; }

        public DateRangeModel()
        {

        }
    }
}

See Also

In this article
Not finding the help you need? Improve this article