Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 10 additions & 19 deletions _contentTemplates/common/dropdowns-virtualization.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,50 @@ Enabling the UI virtualization feature makes the component reuse a set number of
#end



#basics-core
This section will explain the parameters and behaviors that are related to the virtualization feature so you can set it up.

>caption To enable UI virtualization, you need to set the following parameters of the component:

* `ScrollMode` - `Telerik.Blazor.DropDownScrollMode` - set it to `DropDownScrollMode.Virtual`. It defaults to the "regular" scrolling.

* `PopupHeight` - `string` - set the height of the popup element to a valid CSS unit. It must **not** be a `null/empty` string.

* `Height` - `string` - [set the height]({%slug common-features/dimensions%}) in the nested **popup settings** tag of the component. It must **not** be a `null/empty` string.
* `ItemHeight` - `decimal` - set it to the height each individual item will have in the dropdown. Make sure to accommodate the content your items will have and any item template.

* `PageSize` - `int` - defines how many items will actually be rendered and reused. The value determines how many items are loaded on each scroll. The number of items must be large enough according to the `ItemHeight` and `PopupHeight` so that there are more items than the dropdown so there is a scrollbar.
* `PageSize` - `int` - defines how many items will actually be rendered and reused. The value determines how many items are loaded on each scroll. The number of items must be large enough according to the `ItemHeight` and popup `Height`, so that there are more items than the dropdown so there is a scrollbar.

You can find a basic example in the [Local Data](#local-data-example) section below.

>caption For working with [remote data](#remote-data-example), you also need:
#end



#value-mapper-text
the component will call this method to request the model that matches the `Value` it has set. This is required because with remote data the `Value` may not be in the initial collection of `Data` that the component has, and so there would otherwise be no way to extract the `DataTextField` from it to render it. Usually, this method will be called on the initial render only to fetch the data item for the current selection.
the component will call this method to request the model that matches the `Value` it has set. This is required because with remote data the `Value` may not be in the initial collection of data that the component has, and so there would otherwise be no way to extract the `DataTextField` from it to render it. Usually, this method will be called on the initial render only to fetch the data item for the current selection.
#end



#remote-data-specifics
* `OnRead` - `EventCallback` - the component will call this event when the user scrolls with the corresponding offset (`Skip`), `PageSize` and any filters. This lets you optimize the data queries and return only what is needed at the moment, when it is needed.

* `TotalCount` - `int` - the total number of items that the dropdown can have. Needs to take into account any current filtering.
* `OnRead` - `EventCallback` - the component will call this event when the user scrolls with the corresponding offset (`Skip`), `PageSize` and any filters. This lets you optimize the data queries and return only what is needed at the moment, when it is needed. Set the `args.Data` and `args.Total` properties of the event argument object.
#end



#limitations

* When the initially selected item/items are on a page different than the first one, opening the dropdown list will NOT scroll the list to the selected item.

#end



#remote-data-sample-intro
This example showcases sample implementations of:

* An async remote service that returns the data. It is mocked by a static class for this example, you can refactor as needed, and you can find examples of serializing it over the wire in <a href="https://github.com/telerik/blazor-ui/tree/master/grid/datasourcerequest-on-server" target="_blank">this collection of sample projects</a> for the grid component - the approach is identical.

* An `OnRead` event handler that calls that service.

#end


#value-mapper-in-remote-example
* A `ValueMapper` that also calls the service.
#end
#end


#value-in-onread
>important The `OnRead` handler should change **only the data** of the component, and **not** other parameters such as `Value`. This can lead to issues with the asynchronous nature of the event, and race conditions can occur with the arrival of the new data. Moreover, such a change is likely to be unexpected by the user and cause bad UX.
#end
20 changes: 6 additions & 14 deletions common-features/loading-sign.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,16 +358,15 @@ We understand, however, that you might want to disable this feature in some case
@* The data operations (such as filtering, sorting, paging) are slow in this example, but there is no loading sign *@

<TelerikGrid EnableLoaderContainer="false"
Data=@GridData TotalCount=@Total OnRead=@ReadItems
FilterMode=@GridFilterMode.FilterRow Sortable=true Pageable=true EditMode="@GridEditMode.Inline">
TItem="@Employee" OnRead="@ReadItems"
FilterMode="@GridFilterMode.FilterRow"
Sortable="true"
Pageable="true">
<GridColumns>
<GridColumn Field=@nameof(Employee.ID) />
<GridColumn Field=@nameof(Employee.Name) Title="Name" />
<GridColumn Field=@nameof(Employee.HireDate) Title="Hire Date" />
</GridColumns>
<GridToolBar>
<GridCommandButton Command="Add" Icon="add">Add Employee</GridCommandButton>
</GridToolBar>
</TelerikGrid>

@* Everything else here is sample data binding *@
Expand All @@ -376,8 +375,6 @@ We understand, however, that you might want to disable this feature in some case

@code {
public List<Employee> SourceData { get; set; }
public List<Employee> GridData { get; set; }
public int Total { get; set; } = 0;

protected override void OnInitialized()
{
Expand All @@ -390,15 +387,10 @@ We understand, however, that you might want to disable this feature in some case

var datasourceResult = SourceData.ToDataSourceResult(args.Request);

GridData = (datasourceResult.Data as IEnumerable<Employee>).ToList();
Total = datasourceResult.Total;

StateHasChanged();
args.Data = (datasourceResult.Data as IEnumerable<Employee>).ToList();
args.Total = datasourceResult.Total;
}

//This sample implements only reading of the data. To add the rest of the CRUD operations see
//https://docs.telerik.com/blazor-ui/components/grid/editing/overview

private List<Employee> GenerateData()
{
var result = new List<Employee>();
Expand Down
99 changes: 48 additions & 51 deletions components/autocomplete/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ from model: @Role
}
````


## OnChange

The `OnChange` event represents a user action - confirmation of the current value/item. The key differences with `ValueChanged` are:
Expand Down Expand Up @@ -121,32 +120,34 @@ You can use the he `OnRead` event to provide data to the component according to

You can also call remote data through async operations.

When using `OnRead`, make sure to set `TItem` and `TValue`.

>caption Custom Data according to the user input in the AutoComplete

````CSHTML
@SelectedValue
<br />
<TelerikAutoComplete Data="@Suggestions"
<p>@AutoCompleteValue</p>

<TelerikAutoComplete TItem="@String"
OnRead="@ReadItems"
@bind-Value="@AutoCompleteValue"
Filterable="true"
Placeholder="Find what you seek by typing"
@bind-Value="@SelectedValue">
Placeholder="Type anything">
</TelerikAutoComplete>

@code{
public string SelectedValue { get; set; }
@code {
public string AutoCompleteValue { get; set; }
List<string> Suggestions { get; set; } = new List<string>();

async Task ReadItems(AutoCompleteReadEventArgs args)
{
if (args.Request.Filters.Count > 0) // there is user filter input, skips providing data on initialization
if (args.Request.Filters.Count > 0) // wait for user filter input
{
Telerik.DataSource.FilterDescriptor filter = args.Request.Filters[0] as Telerik.DataSource.FilterDescriptor;
string userInput = filter.Value.ToString();
string method = filter.Operator.ToString();

//new data collection comes down from the service
Suggestions = await GetSuggestionsData(userInput, method);
args.Data = await GetSuggestionsData(userInput, method);
}
}

Expand All @@ -157,7 +158,7 @@ You can also call remote data through async operations.
//sample logic for getting suggestions - here they are generated, you can call a remote service
//for brevity, this example does not use the filter operator, but your actual service can
List<string> suggestionsData = new List<string>();
for (int i = 0; i < 5; i++)
for (int i = 1; i <= 5; i++)
{
suggestionsData.Add($"suggestion {i} for input {userInput}");
}
Expand All @@ -172,53 +173,51 @@ You can also call remote data through async operations.
````CSHTML
@using Telerik.DataSource.Extensions

@SelectedValue
<br />
<TelerikAutoComplete Data="@CurrentSuggestions"
OnRead=@ReadItems
Filterable="true"
Placeholder="Find a car by typing part of its make"
@bind-Value="@SelectedValue" ValueField="Make">
<p>@AutoCompleteValue</p>

<TelerikAutoComplete TItem="@Car"
OnRead="@ReadItems"
@bind-Value="@AutoCompleteValue"
ValueField="@nameof(Car.Make)"
Filterable="true"
Placeholder="Type a car brand">
</TelerikAutoComplete>

@code {
public string SelectedValue { get; set; }
public string AutoCompleteValue { get; set; }
List<Car> AllSuggestions { get; set; }

List<Car> CurrentSuggestions { get; set; }

protected async Task ReadItems(AutoCompleteReadEventArgs args)
{
//generate the big data source that we want to narrow down for the user
//in a real case you would probably have fetched it in OnInitializedAsync
if (AllSuggestions == null)
{
AllSuggestions = new List<Car>
{
new Car { Id = 1, Make = "Honda" },
new Car { Id = 2, Make = "Opel" },
new Car { Id = 3, Make = "Audi" },
new Car { Id = 4, Make = "Lancia" },
new Car { Id = 5, Make = "BMW" },
new Car { Id = 6, Make = "Mercedes" },
new Car { Id = 7, Make = "Tesla" },
new Car { Id = 8, Make = "Vw" },
new Car { Id = 9, Make = "Alpha Romeo" },
new Car { Id = 10, Make = "Chevrolet" },
new Car { Id = 11, Make = "Ford" },
new Car { Id = 12, Make = "Cadillac" },
new Car { Id = 13, Make = "Dodge" },
new Car { Id = 14, Make = "Jeep" },
new Car { Id = 15, Make = "Chrysler" },
new Car { Id = 16, Make = "Lincoln" }
};
}

//use Telerik extension methods to filter the data source based on the request from the component
//using Telerik extension methods to filter the data
var datasourceResult = AllSuggestions.ToDataSourceResult(args.Request);
CurrentSuggestions = (datasourceResult.Data as IEnumerable<Car>).ToList();
args.Data = datasourceResult.Data;
}

protected override void OnInitialized()
{
AllSuggestions = new List<Car> {
new Car { Id = 1, Make = "Honda" },
new Car { Id = 2, Make = "Opel" },
new Car { Id = 3, Make = "Audi" },
new Car { Id = 4, Make = "Lancia" },
new Car { Id = 5, Make = "BMW" },
new Car { Id = 6, Make = "Mercedes" },
new Car { Id = 7, Make = "Tesla" },
new Car { Id = 8, Make = "Vw" },
new Car { Id = 9, Make = "Alpha Romeo" },
new Car { Id = 10, Make = "Chevrolet" },
new Car { Id = 11, Make = "Ford" },
new Car { Id = 12, Make = "Cadillac" },
new Car { Id = 13, Make = "Dodge" },
new Car { Id = 14, Make = "Jeep" },
new Car { Id = 15, Make = "Chrysler" },
new Car { Id = 16, Make = "Lincoln" }
};

base.OnInitialized();
}

public class Car
{
public int Id { get; set; }
Expand All @@ -227,8 +226,6 @@ You can also call remote data through async operations.
}
````



## OnBlur

The `OnBlur` event fires when the component loses focus.
Expand Down
41 changes: 17 additions & 24 deletions components/autocomplete/virtualization.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ The AutoComplete @[template](/_contentTemplates/common/dropdowns-virtualization.
![Virtual Scrolling of large local data](images/autocomplete-virtual-scrolling-local.gif)



## Basics

@[template](/_contentTemplates/common/dropdowns-virtualization.md#basics-core)
Expand All @@ -37,7 +36,6 @@ The AutoComplete @[template](/_contentTemplates/common/dropdowns-virtualization.
@[template](/_contentTemplates/common/dropdowns-virtualization.md#limitations)



## Local Data Example


Expand Down Expand Up @@ -73,8 +71,6 @@ The AutoComplete @[template](/_contentTemplates/common/dropdowns-virtualization.
}
````



## Remote Data Example

@[template](/_contentTemplates/common/dropdowns-virtualization.md#remote-data-sample-intro)
Expand All @@ -85,31 +81,30 @@ Run this and see how you can display, scroll and filter over 10k records in the
@using Telerik.DataSource
@using Telerik.DataSource.Extensions

@SelectedValue
<br />
<TelerikAutoComplete Data="@CurentPageOfData"
<p>@AutoCompleteValue</p>

<TelerikAutoComplete TItem="@String"
ScrollMode="@DropDownScrollMode.Virtual"
OnRead="@GetRemoteData"
TotalCount="@TotalItems"
PopupHeight="200px"
ItemHeight="30"
PageSize="20"

@bind-Value="@SelectedValue"
Filterable="true" FilterOperator="@StringFilterOperator.Contains">
OnRead="@GetRemoteData"
@bind-Value="@AutoCompleteValue"
Filterable="true"
FilterOperator="@StringFilterOperator.Contains">
<AutoCompleteSettings>
<AutoCompletePopupSettings Height="300px" />
</AutoCompleteSettings>
</TelerikAutoComplete>

@code{
string SelectedValue { get; set; } = "Name 1234"; // pre-select an item to showcase it works like in a regular textbox
List<string> CurentPageOfData { get; set; }
int TotalItems { get; set; }
@code {
string AutoCompleteValue { get; set; } = "Name 1234"; // pre-select an item to showcase it works like in a regular textbox

async Task GetRemoteData(AutoCompleteReadEventArgs e)
async Task GetRemoteData(AutoCompleteReadEventArgs args)
{
DataEnvelope<string> result = await MyService.GetItems(e.Request);
DataEnvelope<string> result = await MyService.GetItems(args.Request);

CurentPageOfData = result.Data;
TotalItems = result.Total;
args.Data = result.Data;
args.Total = result.Total;
}

// mimics a real service in terms of API appearance, refactor as necessary for your app
Expand Down Expand Up @@ -149,6 +144,4 @@ Run this and see how you can display, scroll and filter over 10k records in the

## See Also

* [Live Demo: AutoComplete Virtualization](https://demos.telerik.com/blazor-ui/autocomplete/virtualization)


* [Live Demo: AutoComplete Virtualization](https://demos.telerik.com/blazor-ui/autocomplete/virtualization)
Loading