New to Telerik UI for Blazor? Download free 30-day trial

Blazor Form Items Overview

You can customize the default editors by using instances of the FormItem tag. Those instances should be in the FormItems collection.

In this article:

FormItem Parameters

Each custom editor is expressed through the FormItem tag. You can define a collection of those editors in the FormItems tag that is a child of the TelerikForm tag. You can find some code examples below.

The FormItem tag exposes the following parameters which you can use to customize the editors:

  • LabelText - string - defines the label for the associated editor. This parameter provides more compact syntax for the <label for="myEditorId"> HTML tag.

  • Id - string - maps to the id HTML attribute of the <input> tag.

  • Hint - string - defines a hint for the user on the place of the validation message. If a validation error occurs the hint will be replaced by the corresponding validation message.

  • Enabled - bool - whether the editor is enabled. Defaults to true. If it is not specifically defined in the FormItem markup, it will take its value from the [Editable] data annotation attribute of the item.

  • Field - string - the name of the field in the model that the editor will render for as a string (case-sensitive). You can set its as a plain string (Field="SomeField") or to have .NET extract the field name from the model for flat models (Field=@nameof(MyModelClass.SomeFIeld)). If you are using its Template to provide a custom editor, the Field parameter is not required.

  • FieldType - string - the data type of the Field. This parameter should be provided if the type of the property in the model can not be extracted using reflection, for example it is an object and you would like to render a NumericTextBox.

  • ColSpan - int - defines the colspan attribute. This parameter is applicable when the FormItems are divided in multiple columns in a single group. See the FormGroups article for an example.

  • Class - string - adds a custom CSS class to the k-form-field div tag.

  • Template - RenderFragment - allows you to change the default editor altogether. For more information see the Template article.

Example

How to use and configure FormItem instances

@* Provide a hint and change the Label of the editors *@

@using System.ComponentModel.DataAnnotations

<TelerikForm Model="@person">
    <FormValidation>
        <DataAnnotationsValidator></DataAnnotationsValidator>
    </FormValidation>
    <FormItems>
        <FormItem Field="@nameof(Person.Id)" Enabled="false" LabelText="Id"></FormItem>
        <FormItem Field="@nameof(Person.FirstName)" LabelText="First name" Hint="Enter your first name"></FormItem>
        <FormItem Field="@nameof(Person.LastName)" LabelText="Last name" Hint="Enter your last name" ColSpan="2"></FormItem>
        <FormItem Field="@nameof(Person.DOB)" LabelText="Date of birth" Hint="Enter your Date of Birth"></FormItem>
    </FormItems>
</TelerikForm>

@code {
    public Person person = new Person();

    public class Person
    {
        public int Id { get; set; } = 10;
        public string FirstName { get; set; } = "John";
        public string LastName { get; set; } = "Doe";
        public DateTime DOB { get; set; } = DateTime.Today.AddYears(-20);
    }
}

Add Form Fields to Autogenerated Ones

To combine manually defined with autogenerated fields, use an instance of the FormAutoGeneratedItems tag inside the FormItems collection.

Basic configuration of the Hybrid Form.

@* Use the FormAutoGeneratedItems tag inside the FormItems to control the autogenerated fields position. *@

@using System.ComponentModel.DataAnnotations

<TelerikForm Model="@person">
    <FormValidation>
        <DataAnnotationsValidator></DataAnnotationsValidator>
    </FormValidation>
    <FormItems>
        <FormItem Field="@nameof(Person.Id)" Enabled="false" LabelText="Id"></FormItem>
        <FormItem Field="@nameof(Person.FirstName)" LabelText="First name" Hint="Enter your first name"></FormItem>
        <FormAutoGeneratedItems></FormAutoGeneratedItems>
    </FormItems>
</TelerikForm>

@code {
    public Person person = new Person();

    public class Person
    {
        public int Id { get; set; } = 10;
        public string FirstName { get; set; } = "John";
        public string LastName { get; set; } = "Doe";
        public DateTime DOB { get; set; } = DateTime.Today.AddYears(-20);
    }
}

UI Rendering inside the Form

When the user changes a value in a non-template Form item, the other Form items don't re-render. This default behavior serves as a performance optimization. In some scenarios, the app may need other form items to update too, for example:

  • When the value in one Form item affects values in other Form items.
  • When Form items show or hide, depending on the value in other Form items.

In such cases, there are a few ways to trigger re-rendering and UI refresh inside or outside the Form:

  • Use a Telerik input component inside a Form item <Template>.
  • Call the Refresh() method of the Form. The method will re-render the Form itself.
  • Subscribe to the OnUpdate event of the Form. The event is an EventCallback, so it will update the whole Razor component, which holds the Form.
  • Call StateHasChanged() inside the Razor component, which holds the Form. This will re-render the whole Razor component, including the Form.

How to re-render all Form Items or the Form's parent component

<p>Type in the Form textboxes and observe the different results.</p>

<p>
    <label>
        <TelerikCheckBox @bind-Value="@ShouldUseOnUpdate" />
        Use the <strong>Form <code>OnUpdate</code> event (an <code>EventCallback</code>)</strong> to re-render inside and outside the Form
    </label>
</p>

<TelerikForm @ref="@FormRef"
             Model="@Employee"
             OnUpdate="@OnFormUpdate">
    <FormItems>
        <FormItem Field="@nameof(Person.Name)" LabelText="Regular FormItem - no re-render without OnUpdate"></FormItem>
        <FormItem>
            <Template>
                <label class="k-label k-form-label" style="color:var(--kendo-color-success)">
                FormItem with &nbsp;<code>&lt;Template&gt;</code>&nbsp; - re-render inside and outside the Form</label>
                <div class="k-form-field-wrap">
                    <TelerikTextBox @bind-Value="@Employee.Name" DebounceDelay="0" />
                </div>
            </Template>
        </FormItem>
        <FormItem>
            <Template>
                <label class="k-label k-form-label" style="color:var(--kendo-color-warning)">
                FormItem with Template and Form &nbsp;<code>Refresh()</code>&nbsp; - re-render inside the Form</label>
                <div class="k-form-field-wrap">
                    <ChildComponent Value="@Employee.Name"
                                   ValueExpression="@( () => Employee.Name )"
                                   OnChange="@OnChildChange_Refresh" />
                </div>
            </Template>
        </FormItem>
        <FormItem>
            <Template>
                <label class="k-label k-form-label" style="color:var(--kendo-color-tertiary)">
                FormItem with Template and &nbsp;<code>StateHasChanged()</code>&nbsp; - re-render inside and outside the Form</label>
                <div class="k-form-field-wrap">
                    <ChildComponent Value="@Employee.Name"
                                   ValueExpression="@( () => Employee.Name )"
                                   OnChange="@OnChildChange_StateHasChanged" />
                </div>
            </Template>
        </FormItem>
    </FormItems>
</TelerikForm>

<br />

<p><code>Employee.Name</code> in UI outside the Form: <strong>@Employee.Name</strong></p>

<TelerikButton OnClick="@( () => { } )"
               ButtonType="@ButtonType.Button">
    Execute EventCallback - re-render inside and outside the Form
</TelerikButton>

@code {
    private TelerikForm? FormRef { get; set; }

    private Person Employee = new Person();

    private bool ShouldUseOnUpdate { get; set; }

    private EventCallback OnFormUpdate => ShouldUseOnUpdate ?
        EventCallback.Factory.Create(this, OnFormUpdateHandler) :
        default(EventCallback);

    private void OnFormUpdateHandler()
    {
        // OnUpdate is an EventCallback.
        // Blazor calls StateHasChanged() automatically to update the UI
        // of the whole Razor component, which holds the Form.
    }

    private void OnChildChange_Refresh(string newValue)
    {
        Employee.Name = newValue;

        if (!ShouldUseOnUpdate)
        {
            FormRef?.Refresh();
        }

    }

    private void OnChildChange_StateHasChanged(string newValue)
    {
        Employee.Name = newValue;

        if (!ShouldUseOnUpdate)
        {
            StateHasChanged();
        }
    }

    protected override void OnInitialized()
    {
        Employee = new Person();

        base.OnInitialized();
    }

    public class Person
    {
        public string Name { get; set; }

        public Person()
        {
            Name = "John Doe";
        }
    }
}
@using System.Linq.Expressions

<TelerikTextBox Value="@Value"
                ValueChanged="@TextBoxValueChanged"
                ValueExpression="@ValueExpression"
                DebounceDelay="0" />

@code {
    [Parameter]
    public string Value { get; set; } = string.Empty;

    // This parameter is an Action instead of EventCallback.
    // It doesn't refresh the whole parent component's UI,
    // for example, for performance optimization.
    [Parameter]
    public Action<string>? OnChange { get; set; }

    // Get a validation expression from a parent component.
    // See https://docs.telerik.com/blazor-ui//blazor-ui/knowledge-base/inputs-validation-child-component
    [Parameter]
    public Expression<Func<string>>? ValueExpression { get; set; }

    private void TextBoxValueChanged(string newValue)
    {
        Value = newValue;

        OnChange?.Invoke(newValue);
    }
}

Next Steps

See Also

In this article