diff --git a/knowledge-base/common-extend-inherit-wrap-reuse-telerik-blazor-components.md b/knowledge-base/common-extend-inherit-wrap-reuse-telerik-blazor-components.md new file mode 100644 index 0000000000..143af62e1b --- /dev/null +++ b/knowledge-base/common-extend-inherit-wrap-reuse-telerik-blazor-components.md @@ -0,0 +1,269 @@ +--- +title: Extend or Inherit Telerik Blazor Components +description: Learn how to extend, inherit, wrap, and reuse Telerik UI for Blazor components, so that the app uses a Telerik component instance with similar settings or behavior at multiple places. +type: how-to +page_title: How to Extend, Inherit, or Wrap Telerik Components for Blazor +slug: common-kb-component-inheritance +tags: telerik, blazor, inheritance +ticketid: 1628856, 1615737, 1604776, 1607228, 1618168 +res_type: kb +--- + +## Environment + + + + + + + + +
ProductUI for Blazor
+ +## Description + +This KB answers the following questions: + +* How to extend and customize Telerik components? +* How to inherit Telerik components and change their properties or methods? +* How to wrap and reuse Telerik components for Blazor? + +## Solution + +There are two ways to extend, inherit, reuse or wrap Telerik components for Blazor. Both of them are demonstrated in the [example below](#example). + +* [Composition—wrap the Telerik component in another Razor component](#wrap-telerik-components) +* [Inheritance—inherit the Telerik component in a C# class](#inherit-telerik-components) + +The sections below discuss the differences between the two alternatives. On the other hand, both options allow you to: + +* Reuse a Telerik component with similar or identical configuration at multiple places in your app. +* Add new parameters. +* Set default values to parameters, so that there is no need to do that everywhere in the app. + +On the other hand, neither option allows changing the internal HTML rendering of the Telerik component. + +> Using both options at the same time is not possible and will lead to runtime exceptions, because such a setup will nest a Telerik component in itself. The following JavaScript error will likely occur: `Cannot read properties of null (reading addEventListener)`. + +### Wrap Telerik Components + +This approach allows you to add additional markup or another components next to the Telerik component. + +1. Add the Telerik component to a separate `.razor` file, for example, `MyReusableComponent.razor`. +1. Implement the desired `MyReusableComponent` parameters and set the required parameters of the Telerik component. +1. Add any other optional content next to the Telerik component. + +### Inherit Telerik Components + +This approach allows you to modify the built-in API and life cycle events of the Telerik component. + +1. Create a class that inhefits from a Telerik component class, for example, `MyInheritedComponent.cs`. +1. Implement API member overrides or change default API member values. + +## Example + +The following example includes three files: + +* `Home.razor` is the component (page) that consumes the inherited and wrapped Telerik components. +* `ReusableComboBox.razor` shows a wrapped Telerik ComboBox. +* `InheritedComboBox.cs` shows an inheriteed Telerik ComboBox. + +Adjust the `YourAppName.BaseComponents` namespace in `Home.razor` and `InheritedComboBox.cs` to run the code successfully in your app. + +
+ +````Home.razor +@page "/" + +@using YourAppName.BaseComponents + +

Telerik ComboBox

+ + + +

Inherited ComboBox with additional API and default property values

+ + + +@InheritedComboBoxCustomProperty + +

Reusable ComboBox with additional rendering, API and default parameter values

+ + + +@ReusableComboBoxCustomProperty + + + +@code { + private InheritedComboBox? InheritedComboBoxRef { get; set; } + private ReusableComboBox? ReusableComboBoxRef { get; set; } + + private List ListItems { get; set; } = new(); + + private int SelectedValue { get; set; } = 3; + + private string InheritedComboBoxCustomProperty { get; set; } = "Get Custom ComboBox Property"; + private string ReusableComboBoxCustomProperty { get; set; } = "Get Custom ComboBox Property"; + + private void OnInheritedButtonClick() + { + InheritedComboBoxCustomProperty = InheritedComboBoxRef?.CustomProperty ?? "Error"; + } + + private void OnReusableButtonClick() + { + ReusableComboBoxCustomProperty = ReusableComboBoxRef?.CustomProperty ?? "Error"; + } + + protected override void OnInitialized() + { + ListItems = new List(); + + for (int i = 1; i <= 24; i++) + { + ListItems.Add(new ListItem() + { + Id = i, + Text = $"Item {i}", + Category = $"Category {i % 6 + 1}" + }); + } + + base.OnInitialized(); + } + + public class ListItem + { + public int Id { get; set; } + public string Text { get; set; } = string.Empty; + public string Category { get; set; } = string.Empty; + } +} +```` +````ReusableComboBox.razor +@using System.Linq.Expressions + +@typeparam TItem +@typeparam TValue + + + + + + +@code { + [Parameter] + public IEnumerable? Data { get; set; } + + [Parameter] + public TValue? Value { get; set; } + + [Parameter] + public EventCallback ValueChanged { get; set; } + + [Parameter] + public Expression>? ValueExpression { get; set; } + + [Parameter] + public string? GroupField { get; set; } + + [Parameter] + public string? TextField { get; set; } + + [Parameter] + public string? ValueField { get; set; } + + [Parameter] + public string Label { get; set; } = "Select Value"; + + private readonly string Id = $"id-{Guid.NewGuid()}"; + + public string CustomProperty + { + get + { + return $"Custom Reusable Property {DateTime.Now.Millisecond}"; + } + } + + private async Task ComboBoxValueChanged(TValue newValue) + { + Value = newValue; + + if (ValueChanged.HasDelegate) + { + await ValueChanged.InvokeAsync(Value); + } + } +} +```` +````InheritedComboBox.cs +using Microsoft.AspNetCore.Components; +using Telerik.Blazor.Components; + +namespace YourAppName.BaseComponents +{ + public class InheritedComboBox : TelerikComboBox + { + public InheritedComboBox() + { + Class = "my-combobox"; + Filterable = true; + FilterOperator = Telerik.Blazor.StringFilterOperator.Contains; + Width = "200px"; + } + + [Parameter] + public string CustomParameter { get; set; } = string.Empty; + + public string CustomProperty + { + get + { + return $"Custom Inherited Property {DateTime.Now.Millisecond}"; + } + } + + // Optional method overrides... + } +} +```` + +## See Also + +* [Using Base Classes with Razor Components](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-9.0#specify-a-base-class)