Add State feature so it will be possible to programmatically save, load and change current state of the ListView.
For example, programmatically open/close item in Edit mode.
=============================
ADMIN EDIT
=============================
A workaround can be achieved using JSInterop
function TriggerClose() {
var btn = document.querySelector(".close-edit");
if (btn && btn.click) {
btn.click();
}
}
@inject IJSRuntime JSInterop
<TelerikButton OnClick="@CloseEdit">Close Edit</TelerikButton>
<TelerikListView Data="@ListViewData" Pageable="true"
OnCreate="@CreateHandler" OnDelete="@DeleteHandler" OnUpdate="@UpdateHandler"
OnEdit="@EditHandler" OnCancel="@CancelHandler">
<EditTemplate>
<div class="edit-template" style="border: 1px solid green; margin: 10px; padding: 10px; display: inline-block;">
<TelerikTextBox @bind-Value="@context.Name" Label="Name" /><br />
<TelerikDropDownList Data="@Teams" @bind-Value="@context.Team" />
<ListViewCommandButton Command="Save" Icon="save">Save</ListViewCommandButton>
<ListViewCommandButton Class="close-edit" Command="Cancel" Icon="cancel">Cancel</ListViewCommandButton>
</div>
</EditTemplate>
<Template>
<div style="border: 1px solid black; margin: 10px; padding: 10px; display: inline-block;">
Employee: @context.Id <br />
Name: @context.Name in team: @context.Team
<ListViewCommandButton Command="Edit" Icon="edit">Edit</ListViewCommandButton>
<ListViewCommandButton Command="Delete" Icon="delete">Delete</ListViewCommandButton>
</div>
</Template>
<HeaderTemplate>
<ListViewCommandButton Command="Add" Icon="plus">Add Employee</ListViewCommandButton>
<p>In this sample, the first item will not open for editing because of the code in the OnEdit handler</p>
</HeaderTemplate>
</TelerikListView>
@code{
List<Employee> ListViewData { get; set; }
List<string> Teams { get; set; }
async Task CloseEdit()
{
await JSInterop.InvokeVoidAsync("TriggerClose");
}
async Task UpdateHandler(ListViewCommandEventArgs args)
{
Employee item = (Employee)args.Item;
// perform actual data source operation here through your service
await MyService.Update(item);
// update the local view-model data with the service data
await GetListViewData();
}
async Task DeleteHandler(ListViewCommandEventArgs args)
{
Employee item = (Employee)args.Item;
// perform actual data source operation here through your service
await MyService.Delete(item);
// update the local view-model data with the service data
await GetListViewData();
}
async Task CreateHandler(ListViewCommandEventArgs args)
{
Employee item = (Employee)args.Item;
// perform actual data source operation here through your service
await MyService.Create(item);
// update the local view-model data with the service data
await GetListViewData();
}
async Task EditHandler(ListViewCommandEventArgs e)
{
Employee currItem = e.Item as Employee;
// prevent opening an item for editing on condition
if (currItem.Id < 2)
{
e.IsCancelled = true;
}
}
async Task CancelHandler(ListViewCommandEventArgs e)
{
Employee changedItem = e.Item as Employee;
// this is the item as the user edited it, but chose to cancel editing/inserting
Console.WriteLine($"user changed item {changedItem.Id} to have Name: {changedItem.Name} and Team: {changedItem.Team}");
}
// data and models follow
async Task GetListViewData()
{
ListViewData = await MyService.Read();
Teams = await MyService.GetTeams();
}
protected override async Task OnInitializedAsync()
{
await GetListViewData();
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Team { get; set; }
}
// the following static class mimics an actual data service that handles the actual data source
// replace it with your actual service through the DI, this only mimics how the API can look like and works for this standalone page
public static class MyService
{
private static List<Employee> _data { get; set; } = new List<Employee>();
private static List<string> _teams = new List<string> { "Sales", "Dev", "Support" };
public static async Task Create(Employee itemToInsert)
{
itemToInsert.Id = _data.Count + 1;
_data.Insert(0, itemToInsert);
}
public static async Task<List<Employee>> Read()
{
if (_data.Count < 1)
{
for (int i = 1; i < 50; i++)
{
_data.Add(new Employee()
{
Id = i,
Name = $"Name {i}",
Team = _teams[i % _teams.Count]
});
}
}
return await Task.FromResult(_data);
}
public static async Task<List<string>> GetTeams()
{
return await Task.FromResult(_teams);
}
public static async Task Update(Employee itemToUpdate)
{
var index = _data.FindIndex(i => i.Id == itemToUpdate.Id);
if (index != -1)
{
_data[index] = itemToUpdate;
}
}
public static async Task Delete(Employee itemToDelete)
{
_data.Remove(itemToDelete);
}
}
}
When you go backwards in the listview paging it exhibits two issues:
- some (almost random) elements remain after the paged elements
- if, as a first action, you go from the last to the first page through the pager buttons, an exception is thrown - Unhandled exception rendering component: Event 112 is already tracked
The DropDownButton/DropDownList in the ListView Template does not open on the user's click after a few interactions.
Steps to reproduce:
Hi,
When using controls like TelerikTextBox/TelerikTextArea in the TelerikListView HeaderTemplate/EditTemplate s you cannot use keyboard navigation in the text.
* Home/End keys do not take you to the start/end of the text
* You cannot use the arrow keys to move the cursor in the text.
If you don't use the mouse to navigate your only option to correct typos is backspace.
The example in your documentation has the same issue. https://docs.telerik.com/blazor-ui/components/listview/editing
Thanks,
Daniel
Hello
Would be great to have a virtualization option on the ListView component, as paging is already supported.
Then we can achieve the "google images" type infinite scrolling without killing performance by loading all without paging...
Below example where we want users to be able to infinitely scroll through images based on keywords;