From d54213042ad68be912b8ca892f458031efd7e284 Mon Sep 17 00:00:00 2001
From: Dimo Dimov <961014+dimodi@users.noreply.github.com>
Date: Thu, 21 Nov 2024 17:21:47 +0200
Subject: [PATCH 1/2] kb(common): Add KB for component inheritance
---
...it-wrap-reuse-telerik-blazor-components.md | 267 ++++++++++++++++++
1 file changed, 267 insertions(+)
create mode 100644 knowledge-base/common-extend-inherit-wrap-reuse-telerik-blazor-components.md
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..4e8723e158
--- /dev/null
+++ b/knowledge-base/common-extend-inherit-wrap-reuse-telerik-blazor-components.md
@@ -0,0 +1,267 @@
+---
+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
+
+
+
+
+
Product
+
UI 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.
+
+> Using both options at the same time is not possible and will lead to runtime errors, because the setup will nest the Telerik component in itself. Possible errors include: `Cannot read properties of null (reading addEventListener)` or `BuildRederTree(RederTreeBuilder): No suitable method found to override`.
+
+### 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)
From dfa089cc5db547ed04d6ffb3230376dfb3d56ec8 Mon Sep 17 00:00:00 2001
From: Dimo Dimov <961014+dimodi@users.noreply.github.com>
Date: Thu, 21 Nov 2024 17:26:09 +0200
Subject: [PATCH 2/2] additional notes
---
...mon-extend-inherit-wrap-reuse-telerik-blazor-components.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
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
index 4e8723e158..143af62e1b 100644
--- a/knowledge-base/common-extend-inherit-wrap-reuse-telerik-blazor-components.md
+++ b/knowledge-base/common-extend-inherit-wrap-reuse-telerik-blazor-components.md
@@ -41,7 +41,9 @@ The sections below discuss the differences between the two alternatives. On the
* Add new parameters.
* Set default values to parameters, so that there is no need to do that everywhere in the app.
-> Using both options at the same time is not possible and will lead to runtime errors, because the setup will nest the Telerik component in itself. Possible errors include: `Cannot read properties of null (reading addEventListener)` or `BuildRederTree(RederTreeBuilder): No suitable method found to override`.
+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