How can I help you?
Custom Value in Blazor MultiSelect Dropdown
5 Mar 202620 minutes to read
The Syncfusion Blazor MultiSelect Dropdown component provides the custom value feature, which enables users to add values that are not present in the predefined data source. This is particularly useful in tag selectors, skill pickers, keyword inputs, and any scenario where the selection set is not fully known in advance.
When a user types a value that does not match any existing item, the component creates a custom list item and places it at the top of the dropdown list. The user must then explicitly select this item from the dropdown to add it to the selection.

NOTE
Custom values are not added to the original
DataSource. They are tracked internally by the component. The original data source remains unmodified throughout the interaction.
Enabling custom value
To enable custom value input, set the AllowCustomValue property to true.
How custom value creation works:
- The user types text in the input field.
- The component checks whether the text matches any existing item in the data source.
- If no match is found, a new list item is created and inserted at the top of the dropdown list.
- The user must explicitly select this custom item from the dropdown list to add it to the selection.
- Only after the item is selected does it appear in the
Valuecollection.
@using Syncfusion.Blazor.DropDowns
<SfMultiSelect TValue="string[]"
TItem="string"
DataSource="@Countries"
AllowCustomValue="true"
Placeholder="Select or enter a country">
</SfMultiSelect>
@code {
private List<string> Countries = new List<string>
{
"United States", "United Kingdom", "Germany", "France", "Japan", "Australia"
};
}
NOTE
If the user types text and does not select the created custom item from the dropdown, the item is not added to the
Valuecollection. Selecting the item from the list is mandatory to complete the addition.
Custom value with complex object types
When the TItem is a complex class, custom values are handled by creating a new instance of the class and assigning the typed input to both the Text and Value field properties. All other properties of the class receive their default values.
Use the CustomValueSpecifier event to supply fully populated custom object instances, including any additional properties that matter for your application logic.
@using Syncfusion.Blazor.DropDowns
<SfMultiSelect TValue="int[]"
TItem="Employee"
DataSource="@Employees"
AllowCustomValue="true"
Placeholder="Select or add an employee">
<MultiSelectFieldSettings Text="Name" Value="Id"></MultiSelectFieldSettings>
<MultiSelectEvents TItem="Employee" TValue="int[]"
CustomValueSpecifier="@OnCustomValue">
</MultiSelectEvents>
</SfMultiSelect>
@code {
private int[] SelectedValues { get; set; }
private List<Employee> Employees = new List<Employee>
{
new Employee { Id = 1, Name = "Alice Martin", Department = "Engineering" },
new Employee { Id = 2, Name = "Bob Johnson", Department = "Marketing" },
new Employee { Id = 3, Name = "Carol Williams", Department = "Finance" }
};
private async Task OnCustomValue(CustomValueEventArgs<Employee> args)
{
// Auto-generate a unique ID and assign defaults for new employees
args.NewData = new Employee
{
Id = Employees.Max(e => e.Id) + 1,
Name = args.Text,
Department = "Pending Assignment"
};
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Department { get; set; }
}
}
NOTE
The
Valuefield, theTextfield, and theValueproperty must be of typestringwhen custom value is enabled and noCustomValueSpecifierevent is used. For non-string value types (such asint), you must handle theCustomValueSpecifierevent and manually setargs.NewDatawith the correct typed value.
CustomValueSpecifier event
The CustomValueSpecifier event fires when a user selects a custom item from the dropdown list. It provides a CustomValueEventArgs<TItem> argument that allows the handler to:
- Inspect the typed text via
args.Text. - Override the created item by assigning a new value to
args.NewData. - Prevent the item from being added to the selection by setting
args.Cancel = true.
| Argument | Type | Description |
|---|---|---|
Text |
string |
The text typed by the user. |
NewData |
TItem |
The new data item being created. Can be replaced with a custom instance. |
Cancel |
bool |
Set to true to prevent the custom value from being added. Default is false. |
Validating custom input
The following example rejects any custom value shorter than three characters.
@using Syncfusion.Blazor.DropDowns
<SfMultiSelect TValue="string[]"
TItem="Tag"
DataSource="@Tags"
AllowCustomValue="true"
Placeholder="Add tags (min. 3 characters)">
<MultiSelectFieldSettings Text="Label" Value="Label"></MultiSelectFieldSettings>
<MultiSelectEvents TItem="Tag" TValue="string[]"
CustomValueSpecifier="@OnCustomValue">
</MultiSelectEvents>
</SfMultiSelect>
@code {
private List<Tag> Tags = new List<Tag>
{
new Tag { Label = "Blazor" },
new Tag { Label = "CSharp" },
new Tag { Label = "WebAssembly" }
};
private async Task OnCustomValue(CustomValueEventArgs<Tag> args)
{
if (args.Text.Length < 3)
{
// Reject entries shorter than 3 characters
args.Cancel = true;
return;
}
args.NewData = new Tag { Label = args.Text };
}
public class Tag
{
public string Label { get; set; }
}
}
NOTE
There is no built-in deduplication for custom values with identical text. If a user selects the same custom text multiple times, each occurrence is treated as a distinct addition. Use the
CustomValueSpecifierevent to implement uniqueness validation.
Visual mode behavior
Custom values work in all visual modes except CheckBox. The display of selected custom values follows the same rendering rules as predefined selections.
Default mode
Selected custom values are displayed as chips that collapse into an overflow indicator when the component loses focus.
<SfMultiSelect TValue="string[]"
TItem="string"
DataSource="@Skills"
AllowCustomValue="true"
Mode="VisualMode.Default"
Placeholder="Select or add skills">
</SfMultiSelect>
@code {
private List<string> Skills = new List<string>
{
"JavaScript", "TypeScript", "Blazor", "React", "Angular"
};
}Box mode
Custom values appear as permanent box-style chips, always visible regardless of focus state.
<SfMultiSelect TValue="string[]"
TItem="string"
DataSource="@Skills"
AllowCustomValue="true"
Mode="VisualMode.Box"
Placeholder="Select or add skills">
</SfMultiSelect>
@code {
private List<string> Skills = new List<string>
{
"JavaScript", "TypeScript", "Blazor", "React", "Angular"
};
}Delimiter mode
Selected custom values are rendered as delimiter-separated text, visually identical to predefined selections.
<SfMultiSelect TValue="string[]"
TItem="string"
DataSource="@Skills"
AllowCustomValue="true"
Mode="VisualMode.Delimiter"
DelimiterChar=";"
Placeholder="Select or add skills">
</SfMultiSelect>
@code {
private List<string> Skills = new List<string>
{
"JavaScript", "TypeScript", "Blazor", "React", "Angular"
};
}
NOTE
Custom value is automatically disabled when Mode is set to
VisualMode.CheckBox. SettingAllowCustomValue="true"alongsideVisualMode.CheckBoxhas no effect; the property is internally forced tofalse.
Custom value with filtering
When AllowFiltering is combined with AllowCustomValue, typing in the input field simultaneously filters existing items and creates a custom entry if no exact match is found. The custom item always appears at the top of the filtered list.
Interaction sequence when both features are enabled:
- User types text — the list filters to show matching items.
- If no exact match exists, a custom item appears at the top of the filtered results.
- The user selects the custom item from the dropdown.
@using Syncfusion.Blazor.DropDowns
<SfMultiSelect TValue="string[]"
TItem="string"
DataSource="@Fruits"
AllowCustomValue="true"
AllowFiltering="true"
Placeholder="Select or type a new fruit">
</SfMultiSelect>
@code {
private List<string> Fruits = new List<string>
{
"Apple", "Banana", "Cherry", "Durian", "Elderberry", "Fig", "Grape"
};
}Custom value with HideSelectedItem
When HideSelectedItem is true, selected custom values are hidden from the dropdown list, consistent with the behavior for predefined selected items.
- Before selection: The custom item is visible at the top of the dropdown.
- After selection: The custom item is hidden from the dropdown list.
- After deselection: The custom item reappears in the dropdown.
<SfMultiSelect TValue="string[]"
TItem="string"
DataSource="@Languages"
AllowCustomValue="true"
HideSelectedItem="true"
Placeholder="Select or add a language">
</SfMultiSelect>
@code {
private List<string> Languages = new List<string>
{
"English", "Spanish", "French", "German", "Mandarin"
};
}Custom value with MaximumSelectionLength
Custom values count toward the MaximumSelectionLength limit. When the maximum is reached, the component prevents further selection, including custom items that appear in the dropdown list.
<SfMultiSelect TValue="string[]"
TItem="string"
DataSource="@Categories"
AllowCustomValue="true"
MaximumSelectionLength="3"
Placeholder="Select up to 3 categories (custom allowed)">
</SfMultiSelect>
@code {
private List<string> Categories = new List<string>
{
"Technology", "Health", "Finance", "Education", "Travel"
};
}Custom value with virtualization
When EnableVirtualization is enabled, custom values receive special internal tracking to maintain their position at the top of the virtual list even as the user scrolls through a large dataset. Custom items are preserved in the component’s internal virtual data collections and are not lost during scrolling.
@using Syncfusion.Blazor.DropDowns
<SfMultiSelect TValue="string[]"
TItem="DataItem"
DataSource="@LargeDataSet"
AllowCustomValue="true"
EnableVirtualization="true"
Placeholder="Select or add items from a large list">
<MultiSelectFieldSettings Text="Name" Value="Code"></MultiSelectFieldSettings>
</SfMultiSelect>
@code {
private List<DataItem> LargeDataSet = Enumerable.Range(1, 10000).Select(i =>
new DataItem { Code = $"ITEM{i:D5}", Name = $"Product {i}" }).ToList();
public class DataItem
{
public string Code { get; set; }
public string Name { get; set; }
}
}Two-way binding with custom values
Custom values fully participate in two-way binding. After a custom item is selected, it is added to the bound Value property. Changes to the Value property from code also correctly reflect custom values in the UI.
@using Syncfusion.Blazor.DropDowns
<SfMultiSelect TValue="string[]"
TItem="string"
DataSource="@Technologies"
AllowCustomValue="true"
@bind-Value="@SelectedTechnologies"
Placeholder="Select or add technologies">
</SfMultiSelect>
<p>Selected: @(SelectedTechnologies != null ? string.Join(", ", SelectedTechnologies) : "None")</p>
@code {
private string[] SelectedTechnologies { get; set; }
private List<string> Technologies = new List<string>
{
"Blazor", "ASP.NET Core", "Entity Framework", "SignalR", "gRPC"
};
}NOTE
Empty or whitespace-only input does not create a custom item. The component ignores such input silently.
Handling the ValueChange event with custom values
The ValueChanged or the ValueChange event fires after a custom value is selected and added to the selection. The event arguments include both predefined and custom values in the Value collection without distinction.
@using Syncfusion.Blazor.DropDowns
<SfMultiSelect TValue="string[]"
TItem="string"
DataSource="@Hobbies"
AllowCustomValue="true"
Placeholder="Select or add hobbies">
<MultiSelectEvents TItem="string" TValue="string[]"
ValueChange="@OnValueChange">
</MultiSelectEvents>
</SfMultiSelect>
<p>Current selection count: @Count</p>
@code {
private int Count { get; set; }
private List<string> Hobbies = new List<string>
{
"Reading", "Cycling", "Cooking", "Gaming", "Hiking"
};
private void OnValueChange(MultiSelectChangeEventArgs<string[]> args)
{
Count = args.Value?.Length ?? 0;
// args.Value contains both predefined and custom selected values
}
}Keyboard interaction
The following keyboard interactions are supported when working with custom values:
| Key | Behavior |
|---|---|
| Down Arrow | Navigates to the custom item at the top of the dropdown list. |
| Up Arrow | Navigates upward through the dropdown list. |
| Enter | Selects the currently highlighted item, including a custom item. |
| Tab | Moves focus away from the component. The unselected custom item is abandoned. |
| Escape | Closes the popup without selecting the custom item. |
NOTE
If a user types a value but does not select the created custom item from the dropdown list, the
Valueproperty is not updated and the item is not added to the selection. Pressing Tab or Escape abandons the custom item.
Type handling
Primitive types
For primitive types such as string, int, and bool, the component attempts to convert the typed input text directly to the target type.
| Type | Behavior |
|---|---|
string |
Input text is used directly as the value. |
int |
Input text is parsed to the integer type. |
bool |
Input text is converted to true or false. |
NOTE
For non-string primitive types, use the
CustomValueSpecifierevent to ensure correct type conversion and to provide a meaningfulNewDatavalue.
Complex object types
For complex class types, the component creates a new instance of TItem and assigns the input text to both the Fields.Text and Fields.Value properties. All other properties default to their type’s default values. The CustomValueSpecifier event should be used to populate additional properties.
NOTE
If type conversion fails for a primitive
TItemtype during custom item creation, the item may be created with an unexpected default value. Use theCustomValueSpecifierevent to handle such cases gracefully.