Getting Started with the ListBox
This tutorial explains how to set up a basic Telerik UI for ASP.NET Core ListBox and highlights the major steps in the configuration of the component.
You will initialize two connected ListBoxes that are bound to remote data, and multiple items can be transferred between the components. By using the client-side API methods, you will select and disable specified items during the ListBox initialization. These items will be sent from the server to the View through the Model. Next, you will handle the ListBox events and display the event data in the browser console. Finally, you can run the sample code in Telerik REPL and continue exploring the components.
Prerequisites
To successfully complete the tutorial, you need a project that is already configured to use the Telerik UI for ASP.NET Core components:
You can use the Telerik REPL playground and skip installing the components on your system and configuring a project.
-
You can prepare a Visual Studio project by following either of these guides:
Creating a new pre-configured project for the Telerik UI for ASP.NET Core components from a project template.
Manually configuring an existing project as described in the First Steps on Windows or First Steps on Mac articles.
1. Prepare the CSHTML File
The first step is to add the required directives at the top of the .cshtml
document:
-
To use the Telerik UI for ASP.NET Core HtmlHelpers:
@using Kendo.Mvc.UI
-
To use the Telerik UI for ASP.NET Core TagHelpers:
@addTagHelper *, Kendo.Mvc
Optionally, you can structure the View content by adding the desired HTML elements like headings, divs, paragraphs, and others.
@using Kendo.Mvc.UI
<h4>Allocate the items in the correct ListBox:</h4>
<div>
</div>
@addTagHelper *, Kendo.Mvc
<h4>Allocate the items in the correct ListBox:</h4>
<div>
</div>
2. Initialize the ListBox
Use the ListBox HtmlHelper or TagHelper to add the component to a page:
- The
Name()
configuration method is mandatory as its value is used for theid
and the name attributes of the ListBox element. - The
DataValueField
andDataTextField
options specify the names of the Model properties that provide the value and text content for each ListBox item. - The
DataSource()
configuration sets the endpoint of theRead
data operation. - The
Selectable()
property enables the multiple items selection. - The
ConnectWith
configuration method specifies theName()
of the target ListBox to which the items can be moved and vice versa. - The
Toolbar
configuration defines the toolbar commands.
@using Kendo.Mvc.UI
<div class="listbox1">
<p>Available products:</p>
@(Html.Kendo().ListBox()
.Name("availableProducts")
.DataValueField("ProductID")
.DataTextField("ProductName")
.DataSource(source => source
.Read(read => read.Action("GetProducts", "ListBox"))
)
.Selectable(ListBoxSelectable.Multiple)
.ConnectWith("unavailableProducts")
.Toolbar(toolbar =>
{
toolbar.Position(ListBoxToolbarPosition.Right);
toolbar.Tools(tools => tools
.MoveUp()
.MoveDown()
.TransferTo()
.TransferFrom()
.TransferAllTo()
.TransferAllFrom()
.Remove());
})
.BindTo(new List<ProductViewModel>())
)
</div>
<div class="listbox2">
<p>Unavailable products:</p>
@(Html.Kendo().ListBox()
.Name("unavailableProducts")
.DataValueField("ProductID")
.DataTextField("ProductName")
.ConnectWith("availableProducts")
.BindTo(new List<ProductViewModel>())
)
</div>
@addTagHelper *, Kendo.Mvc
@{
var products = new List<ProductViewModel>();
var tools = new string[] { "moveUp", "moveDown", "transferTo", "transferFrom", "transferAllTo", "transferAllFrom", "remove" };
}
<div class="listbox1">
<p>Available products:</p>
<kendo-listbox name="availableProducts"
datavaluefield="ProductID"
datatextfield="ProductName"
selectable="ListBoxSelectable.Multiple"
connect-with="unavailableProducts"
bind-to="products">
<datasource>
<transport>
<read url="@Url.Action("GetProducts", "ListBox")"/>
</transport>
</datasource>
<toolbar position="ListBoxToolbarPosition.Right" tools="tools"/>
</kendo-listbox>
</div>
<div class="listbox2">
<p>Unavailable products:</p>
<kendo-listbox name="unavailableProducts"
datavaluefield="ProductID"
datatextfield="ProductName"
selectable="ListBoxSelectable.Multiple"
connect-with="availableProducts"
bind-to="products">
</kendo-listbox>
</div>
public IActionResult GetProducts()
{
var products = Enumerable.Empty<ProductViewModel>();
using (var northwind = GetContext())
{
products = northwind.Products.Select(product => new ProductViewModel
{
ProductID = product.ProductID,
ProductName = product.ProductName
}).ToList();
}
return Json(products);
}
3. Configure the Initially Selected and Disabled Items
The next step is to get a couple of lists with Model (ProductViewModel
) IDs passed from the Controller to the View. The first list contains IDs of ListBox items that must be selected (SelectedProductIDs
) when the component is loaded. The second collection contains the IDs that must be initially disabled (DisabledProductIDs
).
Convert each List<ProductViewModel>
Model property into a comma-separated string and store it in a hidden input element on the page. As a result, there will be two hidden inputs on the page that will contain the product IDs, which must be selected or disabled in the ListBox.
Handle the DataBound
event of the ListBox, which fires when the data is received from the remote service, and use the ListBox client-side API to select and disable the specified items programmatically.
@using Kendo.Mvc.UI
@model ListBoxViewModel
@{
string selectedProductIds = string.Join(",", Model.SelectedProductIDs.Select(x=>x.ProductID).ToArray());
<input type="hidden" id="selected-server-products" value=@selectedProductIds />
}
@{
string disabledProductIds = string.Join(",", Model.DisabledProductIDs.Select(x=>x.ProductID).ToArray());
<input type="hidden" id="disabled-server-products" value=@disabledProductIds />
}
<div class="listbox1">
<p>Available products:</p>
@(Html.Kendo().ListBox()
.Name("availableProducts")
.Events(ev => ev.DataBound("onDataBound"))
.DataValueField("ProductID")
.DataTextField("ProductName")
.DataSource(source => source
.Read(read => read.Action("GetProducts", "ListBox"))
)
.Selectable(ListBoxSelectable.Multiple)
.ConnectWith("unavailableProducts")
.Toolbar(toolbar =>
{
toolbar.Position(ListBoxToolbarPosition.Right);
toolbar.Tools(tools => tools
.MoveUp()
.MoveDown()
.TransferTo()
.TransferFrom()
.TransferAllTo()
.TransferAllFrom()
.Remove());
})
.BindTo(new List<ProductViewModel>())
)
</div>
<div class="listbox2">
<p>Unavailable products:</p>
@(Html.Kendo().ListBox()
.Name("unavailableProducts")
.DataValueField("ProductID")
.DataTextField("ProductName")
.ConnectWith("availableProducts")
.BindTo(new List<ProductViewModel>())
)
</div>
@addTagHelper *, Kendo.Mvc
@model ListBoxViewModel
@{
var products = new List<ProductViewModel>();
var tools = new string[] { "moveUp", "moveDown", "transferTo", "transferFrom", "transferAllTo", "transferAllFrom", "remove" };
}
@{
string selectedProductIds = string.Join(",", Model.SelectedProductIDs.Select(x=>x.ProductID).ToArray());
<input type="hidden" id="selected-server-products" value=@selectedProductIds />
}
@{
string disabledProductIds = string.Join(",", Model.DisabledProductIDs.Select(x=>x.ProductID).ToArray());
<input type="hidden" id="disabled-server-products" value=@disabledProductIds />
}
<div class="listbox1">
<p>Available products:</p>
<kendo-listbox name="availableProducts" on-data-bound="onDataBound"
datavaluefield="ProductID"
datatextfield="ProductName"
selectable="ListBoxSelectable.Multiple"
connect-with="unavailableProducts"
bind-to="products">
<datasource>
<transport>
<read url="@Url.Action("GetProducts", "ListBox")"/>
</transport>
</datasource>
<toolbar position="ListBoxToolbarPosition.Right" tools="tools"/>
</kendo-listbox>
</div>
<div class="listbox2">
<p>Unavailable products:</p>
<kendo-listbox name="unavailableProducts"
datavaluefield="ProductID"
datatextfield="ProductName"
selectable="ListBoxSelectable.Multiple"
connect-with="availableProducts"
bind-to="products">
</kendo-listbox>
</div>
<script>
function onDataBound(e) {
let listBoxReference = e.sender;
//Convert the value of the "selected-server-products" input into array of strings
let idsToSelect = $("#selected-server-products").val().split(',');
//Loop throught the ids that should be selected in the ListBox
$.each(idsToSelect, function(index, id) {
//Get the "uid" of the data item based on the array value
let listBoxItemUID = listBoxReference.dataItems().filter(f => f.ProductID == parseInt(id))[0].uid;
//Get the HTML element of the item that should be selected based on the "uid"
let listBoxElement = listBoxReference.items().filter(function(){
return $(this).attr("data-uid") == listBoxItemUID;
});
//Select the respective item
listBoxReference.select(listBoxElement);
});
//Follow the same logic to disable the ids from the hidden "disabled-server-products" input element
let idsToDisable = $("#disabled-server-products").val().split(',');
$.each(idsToDisable, function(index, id) {
let listBoxItemUID = listBoxReference.dataItems().filter(f => f.ProductID == parseInt(id))[0].uid;
let listBoxElement = listBoxReference.items().filter(function(){
return $(this).attr("data-uid") == listBoxItemUID;
});
listBoxReference.enable(listBoxElement, false);
});
}
</script>
public class HomeController : Controller {
public ActionResult Index()
{
ListBoxViewModel productItems = new ListBoxViewModel()
{
SelectedProductIDs = new List<ProductViewModel>()
{
new ProductViewModel() { ProductID = 2 },
new ProductViewModel() { ProductID = 10 },
new ProductViewModel() { ProductID = 15 }
},
DisabledProductIDs = new List<ProductViewModel>()
{
new ProductViewModel() { ProductID = 5 },
new ProductViewModel() { ProductID = 8 },
new ProductViewModel() { ProductID = 12 }
}
};
return View("Index", productItems);
}
}
public class ListBoxViewModel {
public List<ProductViewModel> SelectedProductIDs { get; set; }
public List<ProductViewModel> DisabledProductIDs { get; set; }
}
public class ProductViewModel {
public int ProductID { get; set; }
public string ProductName { get; set; }
}
4. Handle the ListBox Events
The ListBox exposes various events that you can handle and further customize the functionality of the component. In this tutorial, you will use the Reorder
event to track when the items are reordered.
@using Kendo.Mvc.UI
@(Html.Kendo().ListBox()
.Name("availableProducts")
.Events(events => events.Reorder("onReorder"))
.DataValueField("ProductID")
.DataTextField("ProductName")
.DataSource(source => source
.Read(read => read.Action("GetProducts", "ListBox"))
)
.Selectable(ListBoxSelectable.Multiple)
.Toolbar(toolbar =>
{
toolbar.Position(ListBoxToolbarPosition.Right);
toolbar.Tools(tools => tools
.MoveUp()
.MoveDown()
);
})
.BindTo(new List<ProductViewModel>())
)
<script>
function onReorder(e) {
//Loop through the data items of the moved items
$.each(e.dataItems, function(index, value) {
console.log("Moved item: " + value.ProductName);
});
}
</script>
@addTagHelper *, Kendo.Mvc
@{
var products = new List<ProductViewModel>();
var tools = new string[] { "moveUp", "moveDown" };
}
<kendo-listbox name="availableProducts" on-reorder="onReorder"
datavaluefield="ProductID"
datatextfield="ProductName"
selectable="ListBoxSelectable.Multiple"
bind-to="products">
<datasource>
<transport>
<read url="@Url.Action("GetProducts", "ListBox")"/>
</transport>
</datasource>
<toolbar position="ListBoxToolbarPosition.Right" tools="tools"/>
</kendo-listbox>
<script>
function onReorder(e) {
//Loop through the data items of the moved items
$.each(e.dataItems, function(index, value) {
console.log("Moved item: " + value.ProductName);
});
}
</script>
5. (Optional) Reference Existing ListBox Instances
You can reference the ListBox instances that you have created and build on top of their existing configuration:
-
Use the value of the
Name()
option of the component to establish a reference.<script> $(document).ready(function() { var listBoxReference = $("#availableProducts").data("kendoListBox"); // listBoxReference is a reference to the existing ListBox instance of the helper. }); </script>
Use the ListBox client-side API to control the behavior of the control. In this example, you will use the following methods:
- The
dataItems
method to get all data items to which the control is bound. - The
items
method to obtain theDOM
elements that correspond to the data items. -
The
reorder
method to change the position of a specified item.<script> $(document).ready(function() { var listBoxReference = $("#availableProducts").data("kendoListBox"); //Get the "uid" of the item with ProductName "Queso Cabrales". var itemUID = listBoxReference.dataItems().filter(f => f.ProductName == "Queso Cabrales")[0].uid; //Get the element of the "Queso Cabrales" item by using its "uid". var itemElement = listBoxReference.items().filter(function(){ return $(this).attr("data-uid") == itemUID }); //Move the item at the first position. listBoxReference.reorder(itemElement, 0); }); </script>
For more information on referencing specific helper instances, see the Methods and Events article.
Explore this Tutorial in REPL
You can continue experimenting with the code sample above by running it in the Telerik REPL server playground: