Skip to content

Commit d542130

Browse files
committed
kb(common): Add KB for component inheritance
1 parent 685008e commit d542130

File tree

1 file changed

+267
-0
lines changed

1 file changed

+267
-0
lines changed
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
---
2+
title: Extend or Inherit Telerik Blazor Components
3+
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.
4+
type: how-to
5+
page_title: How to Extend, Inherit, or Wrap Telerik Components for Blazor
6+
slug: common-kb-component-inheritance
7+
tags: telerik, blazor, inheritance
8+
ticketid: 1628856, 1615737, 1604776, 1607228, 1618168
9+
res_type: kb
10+
---
11+
12+
## Environment
13+
14+
<table>
15+
<tbody>
16+
<tr>
17+
<td>Product</td>
18+
<td>UI for Blazor</td>
19+
</tr>
20+
</tbody>
21+
</table>
22+
23+
## Description
24+
25+
This KB answers the following questions:
26+
27+
* How to extend and customize Telerik components?
28+
* How to inherit Telerik components and change their properties or methods?
29+
* How to wrap and reuse Telerik components for Blazor?
30+
31+
## Solution
32+
33+
There are two ways to extend, inherit, reuse or wrap Telerik components for Blazor. Both of them are demonstrated in the [example below](#example).
34+
35+
* [Composition&mdash;wrap the Telerik component in another Razor component](#wrap-telerik-components)
36+
* [Inheritance&mdash;inherit the Telerik component in a C# class](#inherit-telerik-components)
37+
38+
The sections below discuss the differences between the two alternatives. On the other hand, both options allow you to:
39+
40+
* Reuse a Telerik component with similar or identical configuration at multiple places in your app.
41+
* Add new parameters.
42+
* Set default values to parameters, so that there is no need to do that everywhere in the app.
43+
44+
> 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`.
45+
46+
### Wrap Telerik Components
47+
48+
This approach allows you to add additional markup or another components next to the Telerik component.
49+
50+
1. Add the Telerik component to a separate `.razor` file, for example, `MyReusableComponent.razor`.
51+
1. Implement the desired `MyReusableComponent` parameters and set the required parameters of the Telerik component.
52+
1. Add any other optional content next to the Telerik component.
53+
54+
### Inherit Telerik Components
55+
56+
This approach allows you to modify the built-in API and life cycle events of the Telerik component.
57+
58+
1. Create a class that inhefits from a Telerik component class, for example, `MyInheritedComponent.cs`.
59+
1. Implement API member overrides or change default API member values.
60+
61+
## Example
62+
63+
The following example includes three files:
64+
65+
* `Home.razor` is the component (page) that consumes the inherited and wrapped Telerik components.
66+
* `ReusableComboBox.razor` shows a wrapped Telerik ComboBox.
67+
* `InheritedComboBox.cs` shows an inheriteed Telerik ComboBox.
68+
69+
Adjust the `YourAppName.BaseComponents` namespace in `Home.razor` and `InheritedComboBox.cs` to run the code successfully in your app.
70+
71+
<div class="skip-repl"></div>
72+
73+
````Home.razor
74+
@page "/"
75+
76+
@using YourAppName.BaseComponents
77+
78+
<p><strong>Telerik ComboBox</strong></p>
79+
80+
<TelerikComboBox Data="@ListItems"
81+
@bind-Value="@SelectedValue"
82+
GroupField="@nameof(ListItem.Category)"
83+
TextField="@nameof(ListItem.Text)"
84+
ValueField="@nameof(ListItem.Id)"
85+
Class="my-combobox"
86+
Filterable="true"
87+
FilterOperator="@StringFilterOperator.Contains"
88+
Width="200px" />
89+
90+
<p style="margin-top:2em"><strong>Inherited ComboBox</strong> with additional API and default property values</p>
91+
92+
<InheritedComboBox @ref="@InheritedComboBoxRef"
93+
Data="@ListItems"
94+
@bind-Value="@SelectedValue"
95+
GroupField="@nameof(ListItem.Category)"
96+
TextField="@nameof(ListItem.Text)"
97+
ValueField="@nameof(ListItem.Id)"
98+
CustomParameter="foo" />
99+
100+
<TelerikButton OnClick="@OnInheritedButtonClick">@InheritedComboBoxCustomProperty</TelerikButton>
101+
102+
<p style="margin-top:2em"><strong>Reusable ComboBox</strong> with additional rendering, API and default parameter values</p>
103+
104+
<ReusableComboBox @ref="@ReusableComboBoxRef"
105+
Data="@ListItems"
106+
@bind-Value="@SelectedValue"
107+
GroupField="@nameof(ListItem.Category)"
108+
TextField="@nameof(ListItem.Text)"
109+
ValueField="@nameof(ListItem.Id)" />
110+
111+
<TelerikButton OnClick="@OnReusableButtonClick">@ReusableComboBoxCustomProperty</TelerikButton>
112+
113+
<style>
114+
.my-combobox {
115+
border-color: blue;
116+
}
117+
</style>
118+
119+
@code {
120+
private InheritedComboBox<ListItem, int>? InheritedComboBoxRef { get; set; }
121+
private ReusableComboBox<ListItem, int>? ReusableComboBoxRef { get; set; }
122+
123+
private List<ListItem> ListItems { get; set; } = new();
124+
125+
private int SelectedValue { get; set; } = 3;
126+
127+
private string InheritedComboBoxCustomProperty { get; set; } = "Get Custom ComboBox Property";
128+
private string ReusableComboBoxCustomProperty { get; set; } = "Get Custom ComboBox Property";
129+
130+
private void OnInheritedButtonClick()
131+
{
132+
InheritedComboBoxCustomProperty = InheritedComboBoxRef?.CustomProperty ?? "Error";
133+
}
134+
135+
private void OnReusableButtonClick()
136+
{
137+
ReusableComboBoxCustomProperty = ReusableComboBoxRef?.CustomProperty ?? "Error";
138+
}
139+
140+
protected override void OnInitialized()
141+
{
142+
ListItems = new List<ListItem>();
143+
144+
for (int i = 1; i <= 24; i++)
145+
{
146+
ListItems.Add(new ListItem()
147+
{
148+
Id = i,
149+
Text = $"Item {i}",
150+
Category = $"Category {i % 6 + 1}"
151+
});
152+
}
153+
154+
base.OnInitialized();
155+
}
156+
157+
public class ListItem
158+
{
159+
public int Id { get; set; }
160+
public string Text { get; set; } = string.Empty;
161+
public string Category { get; set; } = string.Empty;
162+
}
163+
}
164+
````
165+
````ReusableComboBox.razor
166+
@using System.Linq.Expressions
167+
168+
@typeparam TItem
169+
@typeparam TValue
170+
171+
<span style="display: flex; gap: 1em; align-items: center;">
172+
<label for="@Id" style="font-size: var(--kendo-font-size)">@Label</label>
173+
<TelerikComboBox Data="@Data"
174+
Value="@Value"
175+
ValueChanged="@( (TValue newValue) => ComboBoxValueChanged(newValue) )"
176+
ValueExpression="@ValueExpression"
177+
GroupField="@GroupField"
178+
TextField="@TextField"
179+
ValueField="@ValueField"
180+
Filterable="true"
181+
FilterOperator="@StringFilterOperator.Contains"
182+
Class="my-combobox"
183+
Id="@Id"
184+
Width="200px" />
185+
</span>
186+
187+
@code {
188+
[Parameter]
189+
public IEnumerable<TItem>? Data { get; set; }
190+
191+
[Parameter]
192+
public TValue? Value { get; set; }
193+
194+
[Parameter]
195+
public EventCallback<TValue?> ValueChanged { get; set; }
196+
197+
[Parameter]
198+
public Expression<Func<TValue?>>? ValueExpression { get; set; }
199+
200+
[Parameter]
201+
public string? GroupField { get; set; }
202+
203+
[Parameter]
204+
public string? TextField { get; set; }
205+
206+
[Parameter]
207+
public string? ValueField { get; set; }
208+
209+
[Parameter]
210+
public string Label { get; set; } = "Select Value";
211+
212+
private readonly string Id = $"id-{Guid.NewGuid()}";
213+
214+
public string CustomProperty
215+
{
216+
get
217+
{
218+
return $"Custom Reusable Property {DateTime.Now.Millisecond}";
219+
}
220+
}
221+
222+
private async Task ComboBoxValueChanged(TValue newValue)
223+
{
224+
Value = newValue;
225+
226+
if (ValueChanged.HasDelegate)
227+
{
228+
await ValueChanged.InvokeAsync(Value);
229+
}
230+
}
231+
}
232+
````
233+
````InheritedComboBox.cs
234+
using Microsoft.AspNetCore.Components;
235+
using Telerik.Blazor.Components;
236+
237+
namespace YourAppName.BaseComponents
238+
{
239+
public class InheritedComboBox<TItem, TValue> : TelerikComboBox<TItem, TValue>
240+
{
241+
public InheritedComboBox()
242+
{
243+
Class = "my-combobox";
244+
Filterable = true;
245+
FilterOperator = Telerik.Blazor.StringFilterOperator.Contains;
246+
Width = "200px";
247+
}
248+
249+
[Parameter]
250+
public string CustomParameter { get; set; } = string.Empty;
251+
252+
public string CustomProperty
253+
{
254+
get
255+
{
256+
return $"Custom Inherited Property {DateTime.Now.Millisecond}";
257+
}
258+
}
259+
260+
// Optional method overrides...
261+
}
262+
}
263+
````
264+
265+
## See Also
266+
267+
* [Using Base Classes with Razor Components](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-9.0#specify-a-base-class)

0 commit comments

Comments
 (0)