Hello everyone,
We have opened this Feature Request to gather your insights on the addition of disabled items for the DropDownList.
===
UPDATE: The associated built-in feature is the OnItemRender event, which can help style specific items without a template. Then, use the ValueChanged event to prevent selection of disabled items with the keyboard.
<TelerikDropDownList Data="@Products"
DefaultText="Select Product..."
OnItemRender="@OnDropDownListItemRender"
TextField="@nameof(Product.Name)"
ValueField="@nameof(Product.Id)"
Value="@SelectedProductId"
ValueChanged="@( (int? newValue) => SelectedProductChanged(newValue) )"
Width="200px">
</TelerikDropDownList>
@code {
private List<Product> Products { get; set; } = new();
private TelerikDropDownList<Product, int?>? DropDownListRef { get; set; }
private int? SelectedProductId { get; set; }
private void OnDropDownListItemRender(DropDownListItemRenderEventArgs<Product> args)
{
// args.Item is null for the DefaultText item
if (args.Item != null && !args.Item.Active)
{
args.Class = "k-disabled";
}
}
private void SelectedProductChanged(int? newValue)
{
var newProduct = Products.FirstOrDefault(x => x.Id == newValue);
if (newProduct?.Active == true || !newValue.HasValue)
{
// select only active items or DefaultText
SelectedProductId = newValue;
}
else
{
// skip disabled items during keyboard navigation
var oldProductIndex = Products.FindIndex(x => x.Id == SelectedProductId);
var newProductIndex = Products.FindIndex(x => x.Id == newValue);
if (newProductIndex > oldProductIndex)
{
// skip forward
SelectedProductId = Products[++newProductIndex].Id;
}
else
{
// skip backward
SelectedProductId = Products[--newProductIndex].Id;
}
}
}
protected override void OnInitialized()
{
for (int i = 1; i <= 7; i++)
{
var active = i % 3 != 0;
Products.Add(new Product()
{
Id = i,
Name = (active ? "" : "Disabled ") + "Product " + i,
Active = active
});
}
base.OnInitialized();
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public bool Active { get; set; }
}
}
===
The example below shows the legacy approach to style items as disabled with DropDownList ItemTemplate and prevent clicks with @onclick. Again, use the ValueChanged event to skip disabled items during keyboard navigation.
<TelerikDropDownList Data="@Products"
TItem="@Product"
TValue="@(int?)"
Value="@SelectedProductId"
ValueField="@nameof(Product.Id)"
TextField="@nameof(Product.Name)"
DefaultText="Select Product..."
ValueChanged="@( (int? newValue) => SelectedProductChanged(newValue) )"
Width="200px">
<DropDownListSettings>
<DropDownListPopupSettings Class="disabled-items" />
</DropDownListSettings>
<ItemTemplate>
@{ var p = context as Product; }
<div class="item-div @( !p.Active ? "disabled" : "" )"
@onclick:preventDefault="@(!p.Active)"
@onclick:stopPropagation="@(!p.Active)">
@p.Name
</div>
</ItemTemplate>
</TelerikDropDownList>
<style>
/* remove default item padding to prevent selection outside the template div */
.disabled-items .k-list-item {
padding: 0;
}
/* add back inner padding */
.disabled-items .item-div {
padding: 4px 8px;
}
/* style disabled items */
.disabled-items .disabled {
cursor: not-allowed;
width: 100%;
color: #ccc;
}
</style>
@code {
private List<Product> Products { get; set; }
private int? SelectedProductId { get; set; }
private async Task SelectedProductChanged(int? newValue)
{
var newProduct = Products.FirstOrDefault(x => x.Id == newValue);
if (newProduct?.Active == true || !newValue.HasValue)
{
// select only active items or DefaultText
SelectedProductId = newValue;
}
else
{
// skip disabled items during keyboard navigation
var oldProductIndex = Products.FindIndex(x => x.Id == SelectedProductId);
var newProductIndex = Products.FindIndex(x => x.Id == newValue);
if (newProductIndex > oldProductIndex)
{
// skip forward
SelectedProductId = Products[++newProductIndex].Id;
}
else
{
// skip backward
SelectedProductId = Products[--newProductIndex].Id;
}
}
}
protected override void OnInitialized()
{
Products = new List<Product>();
for (int i = 1; i <= 7; i++)
{
var active = i % 3 != 0;
Products.Add(new Product()
{
Id = i,
Name = (active ? "" : "Disabled ") + "Product " + i,
Active = active
});
}
base.OnInitialized();
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
}
}