The OnBlur event does not fire after removing an item wehn using TagMode="@MultiSelectTagMode.Single"
I used this snippet in the Blazor REPL to reproduce the issue:
<p>@OnBlurMessage</p>
<TelerikMultiSelect Data="@Countries"
@bind-Value="@SelectedCountries"
TagMode="@MultiSelectTagMode.Single"
Placeholder="Enter Balkan country, e.g., Bulgaria"
Width="350px"
ClearButton="true"
AutoClose="false"
OnBlur="OnBlurHandler">
</TelerikMultiSelect>
@code {
private List<string> Countries { get; set; } = new List<string>();
private List<string> SelectedCountries { get; set; } = new List<string>();
string OnBlurMessage {get; set;} = "";
int i;
protected override void OnInitialized()
{
Countries.Add("Albania");
Countries.Add("Bosnia & Herzegovina");
Countries.Add("Bulgaria");
Countries.Add("Croatia");
Countries.Add("Kosovo");
Countries.Add("North Macedonia");
Countries.Add("Montenegro");
Countries.Add("Serbia");
Countries.Add("Slovenia");
base.OnInitialized();
}
void OnBlurHandler()
{
OnBlurMessage = $"OnBlurHandler touched {++i} times";
}
}
Steps to reproduce:
The OnBlur event should fire after step 2.
Attached is a short video clip of what I see.
By design, the filter should be cleared when the user blurs the component. The filter is currently persisted and this is not correct.
Reproducible in the filtering demo.
When @bind-Value is used, the tags are ordered in the way the user chose them, which is the expected behavior.
When you don't use two-way binding, but alter the Value in the ValueChanged event (to implement some logic), the tags get reordered according to the their occurrence in the data source.
I would expect that they remain the user order in all cases.
I have set a small size to the MultiSelect. I noticed that the Summary Tag that contains the "1 more selected" text does not change - its size always remains the same regardless of the component size.
Reproduction: https://blazorrepl.telerik.com/cxFvPxvh58SMoekS04.
The Roundness setting of the MultiSelect also does not affect the summary tag.
I'm seeing a scroll bar appear then disappear as I type. Repeatedly typing "a" in the box will show/hide the scroll bar. Also typing "a" then backspace has the same behavior.
<TelerikMultiSelect Filterable="true" Data="@Countries"
@bind-Value="@Values"
Placeholder="Enter Balkan country, e.g., Bulgaria"
Width="350px" ClearButton="true"
AutoClose="false">
</TelerikMultiSelect>
@if (Values.Count > 0)
{
<ul>
@foreach (var item in Values)
{
<li>@item</li>
}
</ul>
}
@code {
List<string> Countries { get; set; } = new List<string>();
List<string> Values { get; set; } = new List<string>();
protected override void OnInitialized()
{
Countries.Add("Albania");
Countries.Add("Bosnia & Herzegovina");
Countries.Add("Bulgaria");
Countries.Add("Croatia");
base.OnInitialized();
}
}
---
ADMIN EDIT:
Currently, the component works the following way:
The scrollbar is shown by the skeleton and is always present (visible on step 3). The tricky part is that If the user is typing very fast, the Blazor framework bundles 2 renderings together and thus the scrollbar is not visible. The result is that the user sees a very brief flicker with the skeleton. Adding a small delay before showing the skeleton on step 3 will prevent the user from seeing the skeleton and thus remove the impression of seeing a "flicker".
As a workaround, you can hide the skeleton with CSS. This is applicable for all "select" components
<TelerikMultiSelect>
<MultiSelectSettings>
<MultiSelectPopupSettings Class="no-skeleton"></MultiSelectPopupSettings>
</MultiSelectSettings>
</TelerikMultiSelect>
<TelerikComboBox>
<ComboBoxSettings>
<ComboBoxPopupSettings Class="no-skeleton"></ComboBoxPopupSettings>
</ComboBoxSettings>
</TelerikComboBox>
<style>
.no-skeleton .k-skeleton {
display: none;
}
</style>
---
When AutoClose is set to false and you select more than one item, then only the first one will be highlighted in the popup. Items are selected and present in the input but are visually highlighted.
Reproduction
1. Run this REPL sampleI would like to add a feature similar to the Tag Mode in the Kendo suite
===========
ADMIN EDIT
===========
In the meantime, there are two possible workarounds:
1. Mimic the desired 'single' TagMode behavior and display the number of selected items inside the MultiSelect, instead of the selected items themselves.
This approach uses custom CSS, which hides the list of selected items and displays a dynamically updated count value. The most important bits are highlighted:
UI for Blazor 2.30
<TelerikMultiSelect Data="@Products" Class="single-tag-mode"
@bind-Value="@SelectedProductIDs"
ValueField="@nameof(Product.ProductID)"
TextField="@nameof(Product.ProductName)"
Placeholder="Select Products">
</TelerikMultiSelect>
<style>
.single-tag-mode ul.k-reset {
float: left;
}
.single-tag-mode ul.k-reset li.k-button {
display: none;
}
.single-tag-mode ul.k-reset:before {
content: "Selected items: @SelectedProductIDs.Count";
display: inline-block;
line-height: 1.8em;
padding: 0 7px;
vertical-align: bottom;
border: 1px solid rgba(0, 0, 0, 0.08);
background: #f5f5f5 linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.02));
}
</style>
@code {
List<Product> Products = new();
List<int> SelectedProductIDs = new();
protected override async Task OnInitializedAsync()
{
for (int i = 1; i <= 10; i++)
{
Products.Add(new Product()
{
ProductID = i,
ProductName = "ProductName " + i
});
}
await base.OnInitializedAsync();
}
public class Product
{
public int ProductID { get; set; }
public string ProductName { get; set; }
}
}
UI for Blazor 3.0
<TelerikMultiSelect Data="@Products" Class="single-tag-mode"
@bind-Value="@SelectedProductIDs"
ValueField="@nameof(Product.ProductID)"
TextField="@nameof(Product.ProductName)"
Placeholder="Select Products">
</TelerikMultiSelect>
<style>
.single-tag-mode .k-input-values {
float: left;
}
.single-tag-mode .k-input-values .k-chip {
display: none;
}
.single-tag-mode .k-input-values:before {
content: "Selected items: @SelectedProductIDs.Count";
display: inline-block;
line-height: 1.8em;
padding: 0 7px;
vertical-align: bottom;
border: 1px solid rgba(0, 0, 0, 0.08);
background: #f5f5f5 linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.02));
}
</style>
@code {
List<Product> Products = new();
List<int> SelectedProductIDs = new();
protected override async Task OnInitializedAsync()
{
for (int i = 1; i <= 10; i++)
{
Products.Add(new Product()
{
ProductID = i,
ProductName = "ProductName " + i
});
}
await base.OnInitializedAsync();
}
public class Product
{
public int ProductID { get; set; }
public string ProductName { get; set; }
}
}
2. Restrict the component's size and allow scrolling to see all selected items.
Use some custom CSS to set desired height of the container holding the selected items (.k-chip-list) and to control its overflow. You can use the Class parameter of the Multiselect to set your custom CSS class to the main wrapping container of the component and style a specific instance of the component, not all instances on the page/app.
In terms of controlling the container's height, you can:
<style>
.my-multiselect{
overflow: auto;
max-height: 60px;
}
</style>
<TelerikMultiSelect Class="my-multiselect"
Data="@Countries"
@bind-Value="@Values"
Placeholder="Enter Balkan country, e.g., Bulgaria"
Width="350px" ClearButton="true" AutoClose="false">
</TelerikMultiSelect>
@code {
List<string> Countries { get; set; } = new List<string>();
List<string> Values { get; set; } = new List<string>();
protected override void OnInitialized()
{
Countries.Add("Albania");
Countries.Add("Bosnia & Herzegovina");
Countries.Add("Bulgaria");
Countries.Add("Croatia");
Countries.Add("Kosovo");
Countries.Add("North Macedonia");
Countries.Add("Montenegro");
Countries.Add("Serbia");
Countries.Add("Slovenia");
base.OnInitialized();
}
}
In the MultiSelect Component you have Item, Footer, and Header Template sub components. I see no way of providing a template for the selected items. This would be a very nice feature to have.
My specific use case it that I would like to add a tool tip to the selected tags.
Thanks
I have a requirement to be able to select multiple values. I have filtering enabled, but I only want the user to be able to select valid values and not enter custom data. My approach would be to clear any invalid data when the control loses focus. I want the MultiSelect input to be cleared when it looses focus (similar to the ComboBox behavior).
=========================
ADMIN EDIT
=========================
In the meantime, such behavior could be achieved with a JavaScript function called through the JS Interop.
@inject IJSRuntime JsInterop
<TelerikMultiSelect Filterable="true" Data="@Countries"
@bind-Value="@Values"
Placeholder="Enter Balkan country, e.g., Bulgaria"
Width="350px" ClearButton="true"
AutoClose="false" OnBlur="@OnBlurHandler">
</TelerikMultiSelect>
@if (Values.Count > 0)
{
<ul>
@foreach (var item in Values)
{
<li>@item</li>
}
</ul>
}
@code {
List<string> Countries { get; set; } = new List<string>();
List<string> Values { get; set; } = new List<string>();
async Task OnBlurHandler()
{
await JsInterop.InvokeVoidAsync("clearMultiselectInput");
}
protected override void OnInitialized()
{
Countries.Add("Albania");
Countries.Add("Bosnia & Herzegovina");
Countries.Add("Bulgaria");
Countries.Add("Croatia");
Countries.Add("Kosovo");
Countries.Add("North Macedonia");
Countries.Add("Montenegro");
Countries.Add("Serbia");
Countries.Add("Slovenia");
base.OnInitialized();
}
}
You can include the following script tag in your index page or place the function in a separate JavaScript file in your project. This function will clear all instances of the Multiselect inputs, so you don't have to specify separate selectors for each of them. If you only want to work with one instance, you can use another approach.
<script>
function clearMultiselectInput() {
var inputs = document.querySelectorAll(".k-multiselect .k-input-values input");
inputs.forEach(e => e.value = "")
}
</script>
I would like to have the ability to refresh the Multiselect Popup.
Currently, if the AutoClose="false" feature is applied and the items are programmatically selected, you cannot display them as selected while the Popup is opened. You need to close it first to accordingly update the selected items collection in it.
To reproduce:
When re-visiting the input when it has options selected as badges, using keyboard;
First visit of options in drop down, using keyboard:
At the moment, the OnChange even fires when:
The problem with the multiselect is that we have two extra actions:
Based on my testing and the online demos, each selection of an item in the dropdown for the Blazor MultiSelect closes the dropdown.
Is there a way to keep the dropdown open for the user to make multiple selections? The user could then click outside of the dropdown to close the dropdown.
The behavior I am describing is similar to the Kendo UI for jQuery MultiSelect "autoClose" configuration property.
https://docs.telerik.com/kendo-ui/api/javascript/ui/multiselect/configuration/autoclose