From a47350facb9f446e9d73003dd0f42688446da14c Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Wed, 21 May 2025 09:27:22 +0300 Subject: [PATCH 01/37] Fix env variable name --- ai/mcp-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ai/mcp-server.md b/ai/mcp-server.md index 2b5fb288a..27baf6b0d 100644 --- a/ai/mcp-server.md +++ b/ai/mcp-server.md @@ -34,7 +34,7 @@ Use the documentation of your AI-powered MCP client to add the Telerik MCP serve You also need to add your [Telerik licence key](slug:installation-license-key) as an `env` parameter in the `mcp.json` file. There are two options: * (recommended) Use a `TELERIK_LICENSE_PATH` argument and point to your Telerik license file location. -* Use a `TELERIK_LICENSE_KEY` argument and paste your Telerik license key. Make sure to [update the license key](slug:installation-license-key#license-key-updates) when necessary. +* Use a `TELERIK_LICENSE` argument and paste your Telerik license key. Make sure to [update the license key](slug:installation-license-key#license-key-updates) when necessary. ### Visual Studio From 9ee4bf5c4729f2f1003204eb01c10144528955f8 Mon Sep 17 00:00:00 2001 From: radkostanev Date: Wed, 21 May 2025 10:14:14 +0300 Subject: [PATCH 02/37] chore: comment out ai slugs --- getting-started/client-blazor.md | 8 ++++---- getting-started/hybrid-blazor.md | 4 ++-- getting-started/vs-code-integration/introduction.md | 4 ++-- getting-started/vs-integration/introduction.md | 2 +- getting-started/web-app.md | 4 ++-- getting-started/what-you-need.md | 4 ++-- introduction.md | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/getting-started/client-blazor.md b/getting-started/client-blazor.md index 2f8842922..972f41711 100644 --- a/getting-started/client-blazor.md +++ b/getting-started/client-blazor.md @@ -101,9 +101,9 @@ The final step in this tutorial is to use a Telerik UI for Blazor component in a @[template](/_contentTemplates/common/get-started.md#add-component-sample) -## Step 7: Install Telerik AI Coding Assistants + @[template](/_contentTemplates/common/get-started.md#next-steps-after-getting-started) @@ -113,9 +113,9 @@ If you prefer video instructions, you can also check the video tutorial below. -## Next Steps + ## See Also diff --git a/getting-started/hybrid-blazor.md b/getting-started/hybrid-blazor.md index 11e97cc0f..1917be5e6 100644 --- a/getting-started/hybrid-blazor.md +++ b/getting-started/hybrid-blazor.md @@ -114,9 +114,9 @@ namespace MyBlazorMauiAppName Add your desired Telerik Blazor components in the app as in a native Blazor app. Explore the available UI for Blazor components and their features in our [live demos](https://demos.telerik.com/blazor-ui). -### 8. Install Telerik AI Coding Assistants + ## Running the Blazor Hybrid App diff --git a/getting-started/vs-code-integration/introduction.md b/getting-started/vs-code-integration/introduction.md index 67461494b..0b88037f6 100644 --- a/getting-started/vs-code-integration/introduction.md +++ b/getting-started/vs-code-integration/introduction.md @@ -28,6 +28,6 @@ To access the VS Code extension, press `Ctrl`+`Shift`+`P` on Windows/Linux or `C ![launch Telerik Blazor VS Code extension](images/launch-extension.png) -## See Also + diff --git a/getting-started/vs-integration/introduction.md b/getting-started/vs-integration/introduction.md index 39eb903d5..1104ee21d 100644 --- a/getting-started/vs-integration/introduction.md +++ b/getting-started/vs-integration/introduction.md @@ -35,4 +35,4 @@ To access the Telerik Visual Studio extension, go to the **Extensions** > **Tele * [Creating New Projects with Visual Studio](slug:getting-started-vs-integration-new-project) * [Converting Existing Projects with Visual Studio](slug:getting-started-vs-integration-convert-project) * [Downloading the Latest Telerik UI for Blazor Versions](slug:getting-started-vs-integration-latest-version) -* [Telerik GitHub Copilot extension for Blazor](slug:ai-copilot-extension) + diff --git a/getting-started/web-app.md b/getting-started/web-app.md index d279ea385..7fe927126 100644 --- a/getting-started/web-app.md +++ b/getting-started/web-app.md @@ -121,9 +121,9 @@ The final step in this tutorial is to use a Telerik UI for Blazor component in a @[template](/_contentTemplates/common/get-started.md#add-component-sample) -## Step 7: Install Telerik AI Coding Assistants + @[template](/_contentTemplates/common/get-started.md#next-steps-after-getting-started) diff --git a/getting-started/what-you-need.md b/getting-started/what-you-need.md index 4f73679c6..90ed4293a 100644 --- a/getting-started/what-you-need.md +++ b/getting-started/what-you-need.md @@ -261,9 +261,9 @@ The Blazor application is ready to use Telerik components. } ```` -## Install Telerik AI Coding Assistants + @[template](/_contentTemplates/common/get-started.md#next-steps-after-getting-started) diff --git a/introduction.md b/introduction.md index 7a38236ec..d381efc47 100644 --- a/introduction.md +++ b/introduction.md @@ -222,7 +222,7 @@ To use UI for Blazor commercially, you need to Date: Wed, 21 May 2025 14:28:13 +0300 Subject: [PATCH 04/37] chore: reapply ai-related changes (#2978) Co-authored-by: radkostanev --- ai/copilot-extension.md | 2 +- ai/mcp-server.md | 2 +- ai/overview.md | 2 +- getting-started/client-blazor.md | 8 ++++---- getting-started/hybrid-blazor.md | 4 ++-- getting-started/vs-code-integration/introduction.md | 4 ++-- getting-started/vs-integration/introduction.md | 2 +- getting-started/web-app.md | 4 ++-- getting-started/what-you-need.md | 4 ++-- introduction.md | 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ai/copilot-extension.md b/ai/copilot-extension.md index 9ffaa2837..d2087f112 100644 --- a/ai/copilot-extension.md +++ b/ai/copilot-extension.md @@ -4,7 +4,7 @@ page_title: Telerik Blazor GitHub Copilot Extension description: Learn how to add and use the Telerik Blazor GitHub Copilot extension as a Blazor AI coding assistant and code generator for better developer productivity. The Telerik Blazor GitHub Copilot extension provides proprietary context about Telerik UI for Blazor to AI-powered software. slug: ai-copilot-extension tags: telerik,blazor,ai -published: False +published: True position: 10 --- diff --git a/ai/mcp-server.md b/ai/mcp-server.md index 27baf6b0d..915c32600 100644 --- a/ai/mcp-server.md +++ b/ai/mcp-server.md @@ -4,7 +4,7 @@ page_title: Telerik Blazor MCP Server description: Learn how to add and use the Telerik Blazor MCP Server as a Blazor AI coding assistant and code generator for better developer productivity. The Telerik Blazor MCP server provides proprietary context about Telerik UI for Blazor to AI-powered software. slug: ai-mcp-server tags: telerik,blazor,ai -published: False +published: True position: 20 --- diff --git a/ai/overview.md b/ai/overview.md index 75828e8e1..cc6aecffc 100644 --- a/ai/overview.md +++ b/ai/overview.md @@ -4,7 +4,7 @@ page_title: Telerik Blazor AI Tooling Overview description: Learn about the AI-powered developer tools that integrate with your IDE or code editor for greater productivity and enhanced developer experience. slug: ai-overview tags: telerik,blazor,ai -published: False +published: True position: 1 --- diff --git a/getting-started/client-blazor.md b/getting-started/client-blazor.md index 972f41711..2f8842922 100644 --- a/getting-started/client-blazor.md +++ b/getting-started/client-blazor.md @@ -101,9 +101,9 @@ The final step in this tutorial is to use a Telerik UI for Blazor component in a @[template](/_contentTemplates/common/get-started.md#add-component-sample) - +Use the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension) to generate code snippets that include Telerik UI for Blazor components and API. @[template](/_contentTemplates/common/get-started.md#next-steps-after-getting-started) @@ -113,9 +113,9 @@ If you prefer video instructions, you can also check the video tutorial below. - +* Use the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension) to generate code snippets that include Telerik UI for Blazor components and API. ## See Also diff --git a/getting-started/hybrid-blazor.md b/getting-started/hybrid-blazor.md index 1917be5e6..11e97cc0f 100644 --- a/getting-started/hybrid-blazor.md +++ b/getting-started/hybrid-blazor.md @@ -114,9 +114,9 @@ namespace MyBlazorMauiAppName Add your desired Telerik Blazor components in the app as in a native Blazor app. Explore the available UI for Blazor components and their features in our [live demos](https://demos.telerik.com/blazor-ui). - +* Use the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension) to generate code snippets that include Telerik UI for Blazor components and API. ## Running the Blazor Hybrid App diff --git a/getting-started/vs-code-integration/introduction.md b/getting-started/vs-code-integration/introduction.md index 0b88037f6..67461494b 100644 --- a/getting-started/vs-code-integration/introduction.md +++ b/getting-started/vs-code-integration/introduction.md @@ -28,6 +28,6 @@ To access the VS Code extension, press `Ctrl`+`Shift`+`P` on Windows/Linux or `C ![launch Telerik Blazor VS Code extension](images/launch-extension.png) - +* [Telerik GitHub Copilot extension for Blazor](slug:ai-copilot-extension) diff --git a/getting-started/vs-integration/introduction.md b/getting-started/vs-integration/introduction.md index 1104ee21d..39eb903d5 100644 --- a/getting-started/vs-integration/introduction.md +++ b/getting-started/vs-integration/introduction.md @@ -35,4 +35,4 @@ To access the Telerik Visual Studio extension, go to the **Extensions** > **Tele * [Creating New Projects with Visual Studio](slug:getting-started-vs-integration-new-project) * [Converting Existing Projects with Visual Studio](slug:getting-started-vs-integration-convert-project) * [Downloading the Latest Telerik UI for Blazor Versions](slug:getting-started-vs-integration-latest-version) - +* [Telerik GitHub Copilot extension for Blazor](slug:ai-copilot-extension) diff --git a/getting-started/web-app.md b/getting-started/web-app.md index 7fe927126..d279ea385 100644 --- a/getting-started/web-app.md +++ b/getting-started/web-app.md @@ -121,9 +121,9 @@ The final step in this tutorial is to use a Telerik UI for Blazor component in a @[template](/_contentTemplates/common/get-started.md#add-component-sample) - +Use the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension) to generate code snippets that include Telerik UI for Blazor components and API. @[template](/_contentTemplates/common/get-started.md#next-steps-after-getting-started) diff --git a/getting-started/what-you-need.md b/getting-started/what-you-need.md index 90ed4293a..4f73679c6 100644 --- a/getting-started/what-you-need.md +++ b/getting-started/what-you-need.md @@ -261,9 +261,9 @@ The Blazor application is ready to use Telerik components. } ```` - +* Use the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension) to generate code snippets that include Telerik UI for Blazor components and API. @[template](/_contentTemplates/common/get-started.md#next-steps-after-getting-started) diff --git a/introduction.md b/introduction.md index d381efc47..7a38236ec 100644 --- a/introduction.md +++ b/introduction.md @@ -222,7 +222,7 @@ To use UI for Blazor commercially, you need to Date: Wed, 21 May 2025 15:13:07 +0300 Subject: [PATCH 05/37] docs(common): Add AI Coding Assistant (#2980) Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com> --- _contentTemplates/common/get-started.md | 6 ++++++ ai/overview.md | 4 ++-- getting-started/client-blazor.md | 4 ++-- getting-started/hybrid-blazor.md | 4 ++-- getting-started/web-app.md | 4 ++-- getting-started/what-you-need.md | 6 +++--- introduction.md | 2 +- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/_contentTemplates/common/get-started.md b/_contentTemplates/common/get-started.md index a59f43f57..eeb3892e8 100644 --- a/_contentTemplates/common/get-started.md +++ b/_contentTemplates/common/get-started.md @@ -208,4 +208,10 @@ This will make the license key available to all Telerik .NET apps that you devel The [Telerik License Key](slug:installation-license-key) article provides additional details on installing and updating your Telerik license key in different scenarios. [Automatic license key maintenance](slug:installation-license-key#automatic-installation) is more effective and recommended in the long run. +#end + +#ai-coding-assistant-ad + +Use the [Telerik AI Coding Assistant](slug:ai-overview) through the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension). These tools help you receive tips and generate code snippets that include Telerik UI for Blazor components and API. + #end \ No newline at end of file diff --git a/ai/overview.md b/ai/overview.md index cc6aecffc..828b0810a 100644 --- a/ai/overview.md +++ b/ai/overview.md @@ -19,8 +19,8 @@ The Telerik AI Coding Assistant is integrated in: The major differences between these tools are: -* The MCP server is more powerful and can handle more complex prompts that require several requests to the AI model. An MCP-enabled client like GitHub Copilot in **Agent** mode can make changes to your app and rebuild it to verify the AI suggestions. -* The responses of the GitHub Copilot extension may contain shorter or partial code snippets and more explanations how to accomplish the task. When using the MCP server, the AI response is mostly code. +* The MCP server is more powerful and can handle more complex prompts that require several requests to the AI model. An MCP-enabled client like Cursor or GitHub Copilot in **Agent** mode can directly suggest changes to your app and even rebuild it to verify the new AI generated code. +* The responses of the GitHub Copilot extension may contain more explanations how to accomplish the task, and shorter or partial code snippets. When using the MCP server, the AI response is mostly code. ## Getting Started diff --git a/getting-started/client-blazor.md b/getting-started/client-blazor.md index 2f8842922..44a9c688f 100644 --- a/getting-started/client-blazor.md +++ b/getting-started/client-blazor.md @@ -101,9 +101,9 @@ The final step in this tutorial is to use a Telerik UI for Blazor component in a @[template](/_contentTemplates/common/get-started.md#add-component-sample) -## Step 7: Install Telerik AI Coding Assistants +## Step 7: Install the Telerik AI Coding Assistant -Use the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension) to generate code snippets that include Telerik UI for Blazor components and API. +@[template](/_contentTemplates/common/get-started.md#ai-coding-assistant-ad) @[template](/_contentTemplates/common/get-started.md#next-steps-after-getting-started) diff --git a/getting-started/hybrid-blazor.md b/getting-started/hybrid-blazor.md index 11e97cc0f..d0e05ef9a 100644 --- a/getting-started/hybrid-blazor.md +++ b/getting-started/hybrid-blazor.md @@ -114,9 +114,9 @@ namespace MyBlazorMauiAppName Add your desired Telerik Blazor components in the app as in a native Blazor app. Explore the available UI for Blazor components and their features in our [live demos](https://demos.telerik.com/blazor-ui). -### 8. Install Telerik AI Coding Assistants +### 8. Install the Telerik AI Coding Assistant -* Use the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension) to generate code snippets that include Telerik UI for Blazor components and API. +@[template](/_contentTemplates/common/get-started.md#ai-coding-assistant-ad) ## Running the Blazor Hybrid App diff --git a/getting-started/web-app.md b/getting-started/web-app.md index d279ea385..a7e4af95b 100644 --- a/getting-started/web-app.md +++ b/getting-started/web-app.md @@ -121,9 +121,9 @@ The final step in this tutorial is to use a Telerik UI for Blazor component in a @[template](/_contentTemplates/common/get-started.md#add-component-sample) -## Step 7: Install Telerik AI Coding Assistants +## Step 7: Install the Telerik AI Coding Assistant -Use the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension) to generate code snippets that include Telerik UI for Blazor components and API. +@[template](/_contentTemplates/common/get-started.md#ai-coding-assistant-ad) @[template](/_contentTemplates/common/get-started.md#next-steps-after-getting-started) diff --git a/getting-started/what-you-need.md b/getting-started/what-you-need.md index 4f73679c6..378d63510 100644 --- a/getting-started/what-you-need.md +++ b/getting-started/what-you-need.md @@ -37,7 +37,7 @@ The required milestones to obtain and use Telerik UI for Blazor are: 1. Add the [CSS theme and JavaScript file](#css-theme-and-javascript-files). 1. Add the [``](#telerikrootcomponent). 1. [Add components to a view](#add-telerik-components-to-a-view). -1. Install [Telerik Blazor AI coding assistants](#install-telerik-ai-coding-assistants). +1. Install the [Telerik Blazor AI Coding Assistant](#install-the-telerik-ai-coding-assistant). ## NuGet Packages @@ -261,9 +261,9 @@ The Blazor application is ready to use Telerik components. } ```` -## Install Telerik AI Coding Assistants +## Install the Telerik AI Coding Assistant -* Use the [Telerik Blazor MCP server](slug:ai-mcp-server) or the [Telerik Blazor GitHub Copilot extension](slug:ai-copilot-extension) to generate code snippets that include Telerik UI for Blazor components and API. +@[template](/_contentTemplates/common/get-started.md#ai-coding-assistant-ad) @[template](/_contentTemplates/common/get-started.md#next-steps-after-getting-started) diff --git a/introduction.md b/introduction.md index 7a38236ec..b34fc00c0 100644 --- a/introduction.md +++ b/introduction.md @@ -222,7 +222,7 @@ To use UI for Blazor commercially, you need to Date: Wed, 21 May 2025 19:17:04 +0300 Subject: [PATCH 06/37] Merge dimodi-patch-1-2983 into production (#2984) * Update 9-0-0.md * Update upgrade/breaking-changes/9-0-0.md --------- Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com> --- upgrade/breaking-changes/9-0-0.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/upgrade/breaking-changes/9-0-0.md b/upgrade/breaking-changes/9-0-0.md index e0ddb02b1..842ee365d 100644 --- a/upgrade/breaking-changes/9-0-0.md +++ b/upgrade/breaking-changes/9-0-0.md @@ -8,9 +8,15 @@ position: 960 # Breaking Changes in 9.0.0 +## Common + ### Trial and commercial users now use the same product package The trial and commercial product versions merged into a single unified distribution package. The product access now depends on a license key file. This eliminates the need for separate trial downloads. For more information, please refer to the [Telerik License Key](slug:installation-license-key). ### .NET Support -Telerik UI for Blazor 9.0.0 targets .NET 8 and no longer supports .NET 6 and .NET 7. For more information, see [System Requirements](slug:system-requirements). \ No newline at end of file +Telerik UI for Blazor 9.0.0 targets .NET 8 and no longer supports .NET 6 and .NET 7. For more information, see [System Requirements](slug:system-requirements). + +## Window + +The `Centered` parameter is removed. To center the Window programmatically, [reset the `Top` and `Left` parameter values](slug:components/window/position#top-and-left). From dbd2ad3c5d2c5b77c803ebfc70d681c5e21bffd5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 May 2025 19:17:22 +0300 Subject: [PATCH 07/37] docs(Common): Add troubleshooting info for license verification banner (#2985) Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com> --- installation/license-key.md | 22 ++++++++++++++++++++++ troubleshooting/license-key-errors.md | 7 +++++++ 2 files changed, 29 insertions(+) diff --git a/installation/license-key.md b/installation/license-key.md index 38276f946..9dd11fe1d 100644 --- a/installation/license-key.md +++ b/installation/license-key.md @@ -61,6 +61,28 @@ The new license key includes information about all previous purchases. This proc * If you used the [manual license key installation](#manual-installation), then repeat the same steps. * To [update your license key in CI/CD environments](slug:deployment-license-key), get your new license key and update the environment variable value. +## Using Telerik Packages in Referenced Projects + +Telerik UI for Blazor may be used in a referenced project in a multi-project app. For example, in the **Client** project of a WebAssembly app that uses server-side pre-rendering. In such cases, you can briefly see a yellow banner in the browser, which says "We couldn't verify your license key for Telerik UI for Blazor. Please see the build log for details and resolution steps". + +There are two alternative ways to avoid the warning banner: + +* Set `PrivateAssets="none"` to the Telerik UI for Blazor NuGet package registration tag. + ````XML.skip-repl + + ```` + +* Reference the `Telerik.Licensing` package explicitly in all projects that reference other projects with Telerik packages. You can use the same version that is referenced by the `Telerik.UI.for.Blazor` NuGet package, or a newer version. + ````XML.skip-repl + + + + ```` + +## Troubleshooting + +Refer to the [Troubleshooting License Key Errors](slug:troubleshooting-license-key-errors) page to find out what license key warnings you may see during application build and what they mean. + ## Frequently Asked Questions ### Does the license key expire? diff --git a/troubleshooting/license-key-errors.md b/troubleshooting/license-key-errors.md index e918d4aab..8f075b877 100644 --- a/troubleshooting/license-key-errors.md +++ b/troubleshooting/license-key-errors.md @@ -22,6 +22,7 @@ A Telerik license key error may occur in the following scenarios: * The license key is outdated or does not include the product version that you are using. * Your subscription license or trial has expired. * You have different conflicting license keys in the same environment. For example, using one global license key and one in the app. Or, using a license key file together with an environment variable in CI/CD environment. +* Telerik UI for Blazor is used in the **Client** project of a WebAssembly app that uses pre-rendering. In such cases, you can briefly see a yellow banner in the browser, which says "[We couldn't verify your license key for Telerik UI for Blazor. Please see the build log for details and resolution steps](#we-couldn-t-verify-your-license-key-for-telerik-ui-for-blazor-yellow-banner)". Refer to the specific error messages and tips below. @@ -70,6 +71,12 @@ This error applies to subscription licenses. [Renew your subscription](https://w [Purchase a commercial license to continue using Telerik UI for Blazor](https://www.telerik.com/purchase/blazor-ui). +### We couldn't verify your license key for Telerik UI for Blazor (yellow banner) + +This section assumes an existing valid license key, so that the problem is not any of the above. + +If you briefly see a yellow warning banner in the web browser that says "**We couldn't verify your license key**", then refer to [Using Telerik Packages in Referenced Projects](slug:installation-license-key#using-telerik-packages-in-referenced-projects). + ## See Also * [Download and Install License Key](slug:installation-license-key) From 08c4af63ea5fc64d64be0213d25aad0c056d9688 Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Wed, 21 May 2025 21:41:47 +0300 Subject: [PATCH 08/37] docs(common): Polish 9.0 Window changes --- upgrade/breaking-changes/9-0-0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/upgrade/breaking-changes/9-0-0.md b/upgrade/breaking-changes/9-0-0.md index 842ee365d..5983ad4e4 100644 --- a/upgrade/breaking-changes/9-0-0.md +++ b/upgrade/breaking-changes/9-0-0.md @@ -19,4 +19,4 @@ Telerik UI for Blazor 9.0.0 targets .NET 8 and no longer supports .NET 6 and .NE ## Window -The `Centered` parameter is removed. To center the Window programmatically, [reset the `Top` and `Left` parameter values](slug:components/window/position#top-and-left). +The `Centered` parameter is removed. The Window is centered by default if the `Top` and `Left` parameters are equal to an empty string or if they are not set. To center the Window programmatically at any time, [reset the `Top` and `Left` parameter values](slug:components/window/position#top-and-left). From 90ed264d4e5cfb1ed4082b07fec484a021c94969 Mon Sep 17 00:00:00 2001 From: radkostanev Date: Fri, 23 May 2025 09:38:32 +0300 Subject: [PATCH 09/37] chore: update material colors in examples --- docs-builder.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs-builder.yml b/docs-builder.yml index e230a0838..2645f3442 100644 --- a/docs-builder.yml +++ b/docs-builder.yml @@ -88,12 +88,21 @@ demos: material-main: name: Main group: Material - colors: ['#ffffff', '#3f51b5', '#212121'] + colors: ['#fefbff', '#65558f', '#1d1b20'] + material-2: + name: Material 2 + group: Material + colors: ['#ffffff', '#3f51b5', '#424242'] material-main-dark: name: Main Dark tags: [dark] group: Material - colors: ['#121212', '#9fa8da', '#e0e0e0'] + colors: ['#141218', '#d0bcff', '#e6e0e9'] + material-2-dark: + name: Material 2 Dark + tags: [dark] + group: Material + colors: ['#303030', '#3f51b5', '#ffffff'] material-arctic: name: Arctic group: Material From 6fe3f632485edf7364a329ef333087f81e37c570 Mon Sep 17 00:00:00 2001 From: AngelVelinov Date: Thu, 29 May 2025 13:58:49 +0300 Subject: [PATCH 10/37] Add configuration fieled 'gitLastCommitDate' --- docs-builder.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs-builder.yml b/docs-builder.yml index 2645f3442..a967bf0ad 100644 --- a/docs-builder.yml +++ b/docs-builder.yml @@ -19,6 +19,7 @@ table-layout: fixed enable-tabbed-code-blocks: true blazor-repl: true pdf-cover-png-path: ./images/pdf-cover.png +gitLastCommitDateEnabled: true demos: metaFileName: demo.json From c198961b681be92d3282458667f6e4bfd5752e88 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 11:03:04 +0300 Subject: [PATCH 11/37] Merge update-panelbar-docs-2986 into production (#2989) * chore(PanelBar): update field bindings docs * Update components/panelbar/data-binding/overview.md Co-authored-by: Iva Stefanova Koevska-Atanasova * Update components/panelbar/data-binding/overview.md --------- Co-authored-by: Nadezhda Tacheva Co-authored-by: Nadezhda Tacheva <73842592+ntacheva@users.noreply.github.com> Co-authored-by: Iva Stefanova Koevska-Atanasova --- components/panelbar/data-binding/overview.md | 11 ++- components/panelbar/templates/header.md | 83 ++++++++++---------- 2 files changed, 52 insertions(+), 42 deletions(-) diff --git a/components/panelbar/data-binding/overview.md b/components/panelbar/data-binding/overview.md index b3d735677..9381161ec 100644 --- a/components/panelbar/data-binding/overview.md +++ b/components/panelbar/data-binding/overview.md @@ -66,7 +66,7 @@ Each `PanelBarBinding` tag exposes the following properties that refer to item p * ItemsField => Items -* Level - this is used for defining [different bindings for different levels](#multiple-level-bindings). If no level is set, the bindings are taken as default for any level that does not have explicit settings. You should have one `TelerikPanelBarBinding` without a level. +* Level—this is used for defining [custom field bindings](#custom-field-bindings) or [different bindings for different levels](#multiple-level-bindings). If no level is set, the bindings are taken as default for any level that does not have explicit settings. You must have one `TelerikPanelBarBinding` without a level to set the default bindings. >tip There are default values for the field names. If your model names match the defaults, you don't have to define them in the bindings settings. @@ -182,6 +182,15 @@ The following **Example** shows how to define simple binding to match item field ![Blazor PanelBar Data Binding](../images/panelbar-data-binding-basic-example.png) +### Custom Field Bindings + +If you are using custom field names, you must ensure their binding for each level. Otherwise, the PanelBar will not render items where the field bindings are missing. + +For that purpose, you must do either of the following: + +* Add one `TelerikPanelBarBinding` without a level to set the default bindings. +* Add `TelerikPanelBarBinding` for each level where you explicitly set the field bindings to your custom fields. + ### Multiple Level Bindings You can define different binding settings for the different levels of nodes in the PanelBar. With this, the children of a node can consume a different field than their parent, and this may make your application more flexible. If you use [hierarchical data binding](slug:panelbar-data-binding-hierarchical), the children can even use a different field or model from their parent. diff --git a/components/panelbar/templates/header.md b/components/panelbar/templates/header.md index 80a45dd9e..accc52ec2 100644 --- a/components/panelbar/templates/header.md +++ b/components/panelbar/templates/header.md @@ -13,9 +13,9 @@ position: 5 You can control and customize the rendering of the header items in the PanelBar by using the `HeaderTemplate`. It provides a `context` object that you can cast to the type that the PanelBar is bound to. -The `HeaderTemplate` of a level is defined under the `PanelBarBinding` tag. +The `HeaderTemplate` of a level is defined under the `PanelBarBinding` tag. Set the `Level` parameter of the `PanelBarBinding` to specify the level the `HeaderTemplate` must be applied to. -If no levels are defined the `HeaderTemplate` will apply to the entire data. +If the `Level` parameter of the `PanelBarBinding` is not set, the `HeaderTemplate` will apply to the entire data. >caption Use HeaderTemplate to customize the rendering of the headers in the PanelBar @@ -26,7 +26,7 @@ If no levels are defined the `HeaderTemplate` will apply to the entire data. - + @{ var item = context as PanelBarItem; @@ -42,8 +42,9 @@ If no levels are defined the `HeaderTemplate` will apply to the entire data. @code { - public List Items { get; set; } - public IEnumerable ExpandedItems { get; set; } = new List(); + private List Items { get; set; } + + private IEnumerable ExpandedItems { get; set; } = new List(); public class PanelBarItem { @@ -60,50 +61,50 @@ If no levels are defined the `HeaderTemplate` will apply to the entire data. List items = new List(); items.Add(new PanelBarItem() - { - Id = 1, - Text = "Project", - ParentId = null, - HasChildren = false, - Icon = SvgIcon.Folder, - Url = "projectURL.url" - }); + { + Id = 1, + Text = "Project", + ParentId = null, + HasChildren = false, + Icon = SvgIcon.Folder, + Url = "projectURL.url" + }); items.Add(new PanelBarItem() - { - Id = 2, - Text = "Implementation", - ParentId = null, - HasChildren = true, - Icon = SvgIcon.Code - }); + { + Id = 2, + Text = "Implementation", + ParentId = null, + HasChildren = true, + Icon = SvgIcon.Code + }); items.Add(new PanelBarItem() - { - Id = 3, - Text = "C#", - ParentId = 2, - HasChildren = false, - Icon = SvgIcon.Cs - }); + { + Id = 3, + Text = "C#", + ParentId = 2, + HasChildren = false, + Icon = SvgIcon.Cs + }); items.Add(new PanelBarItem() - { - Id = 4, - Text = "HTML 5", - ParentId = 2, - HasChildren = false, - Icon = SvgIcon.Html5 - }); + { + Id = 4, + Text = "HTML 5", + ParentId = 2, + HasChildren = false, + Icon = SvgIcon.Html5 + }); items.Add(new PanelBarItem() - { - Id = 5, - Text = "CSS", - ParentId = 2, - HasChildren = false, - Icon = SvgIcon.Css - }); + { + Id = 5, + Text = "CSS", + ParentId = 2, + HasChildren = false, + Icon = SvgIcon.Css + }); return items; } From 3170b708ce3fed037071163ceeac2c327d01c3e1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 11:03:54 +0300 Subject: [PATCH 12/37] Merge improve-hybrid-docs-2990 into production (#2994) * chore(common): update assets section in hybrid apps docs * Update getting-started/hybrid-blazor.md Co-authored-by: Yordan <60105689+yordan-mitev@users.noreply.github.com> * Update getting-started/hybrid-blazor.md --------- Co-authored-by: Nadezhda Tacheva Co-authored-by: Nadezhda Tacheva <73842592+ntacheva@users.noreply.github.com> Co-authored-by: Yordan <60105689+yordan-mitev@users.noreply.github.com> --- getting-started/hybrid-blazor.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/getting-started/hybrid-blazor.md b/getting-started/hybrid-blazor.md index d0e05ef9a..a31c072b2 100644 --- a/getting-started/hybrid-blazor.md +++ b/getting-started/hybrid-blazor.md @@ -40,9 +40,19 @@ To use the UI for Blazor components, install the `Telerik.UI.for.Blazor` packag ### 3. Add the Telerik Client Assets -To have the Telerik Blazor components look and behave as expected, you need the Telerik [CSS and JavaScript assets](slug:getting-started/what-you-need#css-theme-and-javascript-files). Include the assets inside the `` of the `wwwroot/index.html` file. +To have the Telerik Blazor components look and behave as expected, you need the Telerik CSS and JavaScript assets. -You can add the Telerik resources as [static assets](slug:getting-started/what-you-need#css-theme-and-javascript-files). +1. Add the [theme stylesheet as a static asset](slug:themes-overview#using-a-theme) in your `wwwroot/index.html` file. + +**HTML** + +@[template](/_contentTemplates/common/js-interop-file.md#theme-static-asset-snippet) + +2. Add the `telerik-blazor.js` file to your `wwwroot/index.html` file. + +**HTML** + +@[template](/_contentTemplates/common/js-interop-file.md#js-interop-file-snippet) ### 4. Include @using Statements From 71bbf6410abea9fb89a9ce0faa90f46989a8b370 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 10:17:26 +0300 Subject: [PATCH 13/37] Update docs-builder.yml (#3001) Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com> --- docs-builder.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-builder.yml b/docs-builder.yml index a967bf0ad..3874b46e8 100644 --- a/docs-builder.yml +++ b/docs-builder.yml @@ -142,7 +142,7 @@ excluded-files: ["**/src-a11y/**/*"] liquid-output-delimiter-left: "{{" liquid-output-delimiter-right: "}}" liquid: - uiForBlazorLatestVersion: "9.0" + uiForBlazorLatestVersion: "9.0.0" themesVersion: "11.0.2" meta: From a5fbe2768f97e447aa774f6b196e9f27dd586faf Mon Sep 17 00:00:00 2001 From: JustinR34 <89593857+JustinR34@users.noreply.github.com> Date: Fri, 6 Jun 2025 03:19:28 -0400 Subject: [PATCH 14/37] Update formgroups.md (#2995) Added more description to the ColumnSpacing parameter. Removed Unnecessary and possibly misleading usage of the ColumnSpacing parameter in the example. --- components/form/formgroups.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/form/formgroups.md b/components/form/formgroups.md index 5ff7da282..5919bfc08 100644 --- a/components/form/formgroups.md +++ b/components/form/formgroups.md @@ -25,7 +25,7 @@ The `FormGroup` tag exposes the following parameters: * `Columns` - `int` - defines the number of columns in the group. -* `ColumnSpacing` - `string` - defines the space between the editors in the group. +* `ColumnSpacing` - `string` - defines the horizontal space between the editors in the group. ## Example - Organize FormItems into Groups @@ -51,7 +51,7 @@ You can organize some FormItems into logical groups. You can configure the label - + From 3e4c28b01ff3c6d202c676757a3347e829c250fb Mon Sep 17 00:00:00 2001 From: JustinR34 <89593857+JustinR34@users.noreply.github.com> Date: Fri, 6 Jun 2025 03:20:22 -0400 Subject: [PATCH 15/37] Update overview.md (#2996) Shouldn't this say horizontal space? or maybe just space.. --- components/form/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/form/overview.md b/components/form/overview.md index 57643d171..989fe67a8 100644 --- a/components/form/overview.md +++ b/components/form/overview.md @@ -207,7 +207,7 @@ The [Blazor Form](https://demos.telerik.com/blazor-ui/form/overview) exposes mul |-----------|------------------------|-------------| | `ButtonsLayout` | `FormButtonsLayout` enum
(`Start`) | Determines the position and width of all Form buttons. See [Form Buttons](slug:form-formitems-buttons). | | `Columns` | `int` | Defines the number of columns in the Form. See the [Columns](slug:form-columns) article for more information | -| `ColumnSpacing` | `string` | Defines the amout of vertical space between the Columns. See the [Columns](slug:form-columns) article for more information. | +| `ColumnSpacing` | `string` | Defines the amout of horizontal space between the Columns. See the [Columns](slug:form-columns) article for more information. | | `Orientation` | `FormOrientation` enum
(`Vertical`) | Determines the position of each label with regard to its editor. See [Orientation](slug:form-orientation) for more information. | ### Styling and Appearance From 28785728d71b3fa57cc0ed8358c7681b24b892c8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 10:21:16 +0300 Subject: [PATCH 16/37] Merge dimodi-patch-2-tabstrip-2999 into production (#3002) * docs(TabStrip): Set tab ID as parameter * Update events.md --------- Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com> --- components/tabstrip/events.md | 15 +++++++++------ components/tabstrip/tabs-collection.md | 12 ++++++------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/components/tabstrip/events.md b/components/tabstrip/events.md index 2753e31fd..4f29d6340 100644 --- a/components/tabstrip/events.md +++ b/components/tabstrip/events.md @@ -17,19 +17,21 @@ This article explains the events available in the Telerik TabStrip for Blazor: ## ActiveTabIdChanged -The `ActiveTabIdChanged` event fires when the user changes the active tab. The event handler receives the new tab ID of type `string` as an argument. This event is designed to work with the new [`ActiveTabId` parameter](slug:tabstrip-tabs-collection). +The `ActiveTabIdChanged` event fires when the user changes the active tab. The event handler receives the new tab ID of type `string` as an argument. If the `Id` parameter of the `TabStripTab` is not set, the component will generate one automatically. + +The `ActiveTabIdChanged` event is designed to work with the new [`ActiveTabId` parameter](slug:tabstrip-tabs-collection). >caption Handle the tab ID selection changed event ````RAZOR - + First tab content. Click through the tabs. - + Second tab content. - + Third tab content. @@ -37,10 +39,11 @@ The `ActiveTabIdChanged` event fires when the user changes the active tab. The e @Result @code { - private string Result { get; set; } + private string Result { get; set; } = string.Empty; + private void HandleTabIdChange(string tabId) { - Result = $"Current tab ID is {tabId}"; + Result = $"The current tab ID is {tabId}"; } } ```` diff --git a/components/tabstrip/tabs-collection.md b/components/tabstrip/tabs-collection.md index 77d740a82..49d4ece1c 100644 --- a/components/tabstrip/tabs-collection.md +++ b/components/tabstrip/tabs-collection.md @@ -27,7 +27,7 @@ To deactivate all tabs, set the ActiveTabId parameter to `string.Empty`. @{ foreach (var tab in Tabs) { - + @tab.Title @@ -54,11 +54,11 @@ To deactivate all tabs, set the ActiveTabId parameter to `string.Empty`. private string ActiveTabId { get; set; } private List Tabs { get; set; } = new List -{ - new Tab { Id = "home", Title = "🏠 Home", Visible = true, Disabled = false }, - new Tab { Id = "profile", Title = "👤 Profile", Visible = true, Disabled = false }, - new Tab { Id = "settings", Title = "⚙️ Settings", Visible = true, Disabled = false } -}; + { + new Tab { Id = "home", Title = "🏠 Home", Visible = true, Disabled = false }, + new Tab { Id = "profile", Title = "👤 Profile", Visible = true, Disabled = false }, + new Tab { Id = "settings", Title = "⚙️ Settings", Visible = true, Disabled = false } + }; public class Tab { From acf90119bf0759e05917d35dcb0b17e47798dc69 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 10:22:31 +0300 Subject: [PATCH 17/37] Merge dimodi-patch-1-2997 into production (#3003) * kb(Grid): Update KB to work in Safari * Update knowledge-base/grid-remove-group-indent.md --------- Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com> --- knowledge-base/grid-remove-group-indent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/knowledge-base/grid-remove-group-indent.md b/knowledge-base/grid-remove-group-indent.md index e48cb8ea0..fb0bdb566 100644 --- a/knowledge-base/grid-remove-group-indent.md +++ b/knowledge-base/grid-remove-group-indent.md @@ -48,7 +48,7 @@ To remove the group indent in the [Grid for Blazor](slug:grid-overview) and hide Date: Fri, 13 Jun 2025 13:07:32 +0300 Subject: [PATCH 28/37] chore(TabStrip): add kb for adding and removing tabs (#2998) * chore(TabStrip): add kb for adding and removing tabs * chore: polish the example and update article content * polish KB article --------- Co-authored-by: Tsvetomir Hristov <106250052+Tsvetomir-Hr@users.noreply.github.com> Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com> --- components/tabstrip/tabs-collection.md | 5 + knowledge-base/tabstrip-dynamic-tabs.md | 186 ++++++++++++++++++++++-- 2 files changed, 182 insertions(+), 9 deletions(-) diff --git a/components/tabstrip/tabs-collection.md b/components/tabstrip/tabs-collection.md index 49d4ece1c..a69aaf9b6 100644 --- a/components/tabstrip/tabs-collection.md +++ b/components/tabstrip/tabs-collection.md @@ -70,6 +70,11 @@ To deactivate all tabs, set the ActiveTabId parameter to `string.Empty`. } ```` +## Add and Remove Tabs + +If you are iterating through a collection to render the tabs and you need to allow the users to add and remove tabs, you may use the `ActiveTabId` parameter to set the active tab after adding and removing tabs. See details and example in this article: [Add and Remove Tabs](slug:tabstrip-kb-add-remove-tabs). + + ## See Also * [TabStrip Events](slug:tabstrip-events) diff --git a/knowledge-base/tabstrip-dynamic-tabs.md b/knowledge-base/tabstrip-dynamic-tabs.md index b2ae2f693..d8b889505 100644 --- a/knowledge-base/tabstrip-dynamic-tabs.md +++ b/knowledge-base/tabstrip-dynamic-tabs.md @@ -1,11 +1,11 @@ --- -title: Dynamic Tabs -description: How to create Dynamic Tabs in TabStip. +title: Add and Remove TabStrip Tabs +description: Learn how to dynamically add and remove tabs type: how-to -page_title: Dynamic Tabs -slug: tabstrip-kb-dynamic-tabs -position: -tags: +page_title: How to Add and Remove TabStrip Tabs +slug: tabstrip-kb-add-remove-tabs +tags: telerik,blazor,tabstrip,add tabs,remove tabs +ticketid: res_type: kb --- @@ -20,12 +20,180 @@ res_type: kb - ## Description -How to create Dynamic Tabs in TabStip? How to add and remove tabs dynamically? How to get information about the currently active tab? How to set the content of the tabs dynamically? +I have a collection of items representing separate tabs. I am iterating through that collection to render a tab for each item as shown in the [Tabs Collection article](slug:tabstrip-tabs-collection). I want to allow the user to add and remove tabs. How to achieve that? + +This KB article also answers the following questions: +* How to implement add and remove tab functionality with the Telerik TabStrip component. +* How to remove a tab using an "X" button in the tab header. +* How to add a new tab with a "+" button, similar to browser tab controls. +* How to position the add ("+") button next to the last tab header. ## Solution -An example is available in the following project: [https://github.com/telerik/blazor-ui/tree/master/tabstrip/DynamicTabs](https://github.com/telerik/blazor-ui/tree/master/tabstrip/DynamicTabs). \ No newline at end of file +1. [Render the TabStrip tabs in a loop](slug:tabstrip-tabs-collection). +1. Use a [`HeaderTemplate`](slug:tabstrip-header-template) for the tabs to add Remove buttons. You can display the buttons conditionally based on the tab count. +1. Declare a button for adding new tabs. +1. Use custom styling and JavaScript to position the Add button next to the last tab header. + +>caption Adding and removing TabStrip tabs at runtime + +````RAZOR +@inject IJSRuntime JS + +
+ + + + @foreach (Tab tab in Tabs) + { + + +
+ @tab.Title + @if (Tabs.Count > 1) + { + + } +
+
+ + Content for @tab.Title + +
+ } +
+
+ + + +@* Move JavaScript code to a JS file *@ + + + +@code { + private List Tabs = new List() + { + new Tab { Title = "Tab 1" }, + new Tab { Title = "Tab 2" }, + new Tab { Title = "Tab 3" } + }; + + private string ActiveTabId { get; set; } = string.Empty; + + private bool ShouldPositionAddButton { get; set; } + + private int LastTabNumber { get; set; } = 3; + + private void AddTab() + { + Tab tabToAdd = new Tab { Id = Guid.NewGuid().ToString(), Title = $"New Tab {++LastTabNumber}" }; + + Tabs.Add(tabToAdd); + + //In this example, we are always activating the newly added tab. Adjust the logic to activate a different tab if needed. + ActiveTabId = tabToAdd.Id; + + ShouldPositionAddButton = true; + } + + private void RemoveTab(Tab tab) + { + if (Tabs.Count <= 1) + { + return; + } + + // Activate the tab after or before the removed one if it's active + if (ActiveTabId == tab.Id) + { + int removedTabIndex = Tabs.FindIndex(x => x.Id == tab.Id); + if (removedTabIndex == Tabs.Count - 1) + { + ActiveTabId = Tabs.ElementAt(removedTabIndex - 1).Id; + } + else + { + ActiveTabId = Tabs.ElementAt(removedTabIndex + 1).Id; + } + } + + Tabs.Remove(tab); + + ShouldPositionAddButton = true; + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender || ShouldPositionAddButton) + { + ShouldPositionAddButton = false; + await JS.InvokeVoidAsync("positionAddTabButton"); + } + + await base.OnAfterRenderAsync(firstRender); + } + + public class Tab + { + public string Id { get; set; } = Guid.NewGuid().ToString(); + + public string Title { get; set; } = string.Empty; + } + +} +```` + +## See Also + +* [Dynamic Tab Collection](slug:tabstrip-tabs-collection) +* [TabStrip Tab `HeaderTemplate`](slug:tabstrip-header-template) From edc604ba87e83426fdd5a5df459ff8ab9f023f1c Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 13:12:24 +0300 Subject: [PATCH 29/37] docs(Form): Minor FluentValidation improvements --- components/form/validation.md | 2 +- .../form-fluent-validation-cannot-validate-instances-of-type.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/form/validation.md b/components/form/validation.md index 5061a05af..f092d624f 100644 --- a/components/form/validation.md +++ b/components/form/validation.md @@ -231,7 +231,7 @@ You can use third-party validation libraries that integrate with the standard `E The example below: * Requires the [`Blazored.FluentValidation` NuGet package](https://www.nuget.org/packages/Blazored.FluentValidation). Also refer to the [FluentValidation documentation](https://docs.fluentvalidation.net/en/latest/blazor.html). -* Shows how to pass `ValueExpression` from the parent component to custom child components in a [Form item template](slug:form-formitems-template) or a [Grid editor template](slug:grid-templates-editor). If the `ValueExpression` is not passed correctly, the app will throw [exception similar to: `Cannot validate instances of type 'ComponentName'. This validator can only validate instances of type 'ModelClassName'`](slug:form-kb-fluent-validation-cannot-validate-instances-of-type). +* Shows how to pass `ValueExpression` from a parent component to optional custom child components in a [Form item template](slug:form-formitems-template) or a [Grid editor template](slug:grid-templates-editor). If the `ValueExpression` is not passed correctly, the app will throw [exception similar to: `Cannot validate instances of type 'ComponentName'. This validator can only validate instances of type 'ModelClassName'`](slug:form-kb-fluent-validation-cannot-validate-instances-of-type). >caption Using FluentValidation diff --git a/knowledge-base/form-fluent-validation-cannot-validate-instances-of-type.md b/knowledge-base/form-fluent-validation-cannot-validate-instances-of-type.md index 930ca7ead..2e16beb57 100644 --- a/knowledge-base/form-fluent-validation-cannot-validate-instances-of-type.md +++ b/knowledge-base/form-fluent-validation-cannot-validate-instances-of-type.md @@ -44,7 +44,7 @@ The issue is not related to or caused by Telerik UI for Blazor. The same behavio ## Solution -1. Define a public parameter of type `Expression>`, which receives the correct expression from the parent component. `T` is the value type, which the custom child component is editing. The parameter name must be consistent with the other two related parameter names that deal the two-way value binding: +1. Define a public parameter of type `Expression>` in the child component. The purpose of this parameter is to receive the correct expression from the parent component. `T` is the value type, which the custom child component is editing. The parameter name must be consistent with the other two related parameter names that deal the two-way value binding: * `Foo` * `FooChanged` * `FooExpression` From 2a6a8cc96b7198f2c82a82fafacc6533bc4f7b58 Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 13:48:45 +0300 Subject: [PATCH 30/37] docs(Grid, TreeList): Improve TableWidth documentation in the State articles (#3020) --- _contentTemplates/grid/state.md | 30 ++++++++++++++++++++++++++---- components/grid/state.md | 2 +- components/treelist/state.md | 2 +- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/_contentTemplates/grid/state.md b/_contentTemplates/grid/state.md index 5c64aefa3..9eaaadb69 100644 --- a/_contentTemplates/grid/state.md +++ b/_contentTemplates/grid/state.md @@ -716,14 +716,17 @@ + Reorderable="true" + Resizable="true"> Reorder Price and Quantity - Make Id Column Last + Resize Columns - Reset Column Order + Reset Column Configuration @@ -784,13 +787,32 @@ } } - private async Task ResetColumnOrder() + private async Task ResizeColumns() + { + if (GridRef != null) + { + var gridState = GridRef.GetState(); + int newColumnWidth = 160; + + foreach (GridColumnState columnState in gridState.ColumnStates) + { + columnState.Width = $"{newColumnWidth}px"; + } + + gridState.TableWidth = $"{newColumnWidth * gridState.ColumnStates.Count}px"; + + await GridRef.SetStateAsync(gridState); + } + } + + private async Task ResetColumns() { if (GridRef != null) { var gridState = GridRef.GetState(); gridState.ColumnStates = new List(); + gridState.TableWidth = null; await GridRef.SetStateAsync(gridState); } diff --git a/components/grid/state.md b/components/grid/state.md index 049bc989f..fb6c7f7b6 100644 --- a/components/grid/state.md +++ b/components/grid/state.md @@ -43,7 +43,7 @@ The Grid state is a generic [class `GridState`](slug:Telerik.Blazor.Compo | `SelectedItems` | `ICollection` | The currently [selected data item(s)](slug:grid-selection-overview). | | `Skip` | `int?` | The number of scrolled data items when using [virtual row scrolling](slug:components/grid/virtual-scrolling). In other words, this is the number of rows above the currently visible ones. | | `SortDescriptors` | `ICollection` | The currently applied [sorts](slug:components/grid/features/sorting). | -| `TableWidth` | `string` | The sum of all visible column widths. This property changes together with `ColumnStates`. The `OnStateChanged` event does not fire separately for it. | +| `TableWidth` | `string` | The sum of all visible column widths. The initial value is always `null` regardless of the column configuration. The `TableWidth` value changes during column resizing together with `ColumnStates` and the`OnStateChanged` event does not fire separately for it. When you resize a column programmatically, and all other columns already have widths, you must update the `TableWidth` too, otherwise the other columns will resize unexpectedly. | \* `TItem` is the Grid model type. diff --git a/components/treelist/state.md b/components/treelist/state.md index 4c16a7bb6..30b0aa827 100644 --- a/components/treelist/state.md +++ b/components/treelist/state.md @@ -42,7 +42,7 @@ The TreeList state is a generic [class `TreeListState`](slug:Telerik.Blaz | `SelectedItems` | `ICollection` | The currently [selected data item(s)](slug:treelist-selection-overview). | | `Skip` | `int?` | The number of scrolled data items when using [virtual row scrolling](slug:treelist-virtual-scrolling). In other words, this is the number of rows above the currently visible ones. | | `SortDescriptors` | `ICollection` | The currently applied [sorts](slug:treelist-sorting). | -| `TableWidth` | `string` | The sum of all visible column widths. This property changes together with `ColumnStates`. The `OnStateChanged` event does not fire separately for it. | +| `TableWidth` | `string` | The sum of all visible column widths. The initial value is always `null` regardless of the column configuration. The `TableWidth` value changes during column resizing together with `ColumnStates` and the`OnStateChanged` event does not fire separately for it. When you resize a column programmatically, and all other columns already have widths, you must update the `TableWidth` too, otherwise the other columns will resize unexpectedly. | \* `TItem` is the TreeList model type. From 7368c550a6cc6474977f963be0efa926a986d9c0 Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 15:27:48 +0300 Subject: [PATCH 31/37] docs(ToggleButton): Do not set Selected in OnClick (#3022) --- components/togglebutton/events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/togglebutton/events.md b/components/togglebutton/events.md index 340425b28..da7215faa 100644 --- a/components/togglebutton/events.md +++ b/components/togglebutton/events.md @@ -23,7 +23,7 @@ The `OnClick` event fires when the user clicks or taps the button, or presses `E The event handler receives argument of type [MouseEventArgs](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.components.web.mouseeventargs). -The `OnClick` event fires before `SelectedChanged`. +The `OnClick` event fires before `SelectedChanged`. Do not change the `Selected` parameter value in the `OnClick` event if the `OnClick` handler is asynchronous. Control the `Selected` parameter value in the [`SelectedChanged` event](#selectedchanged). >caption Handle the Toggle Button OnClick event From 53f866b9c24d221ad16d63c2563278ed5cf62541 Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 17:29:58 +0300 Subject: [PATCH 32/37] docs(DockManager): Add missing UnpinnedSize and UnpinnedSizeChanged (#3026) * docs(DockManager): Add missing UnpinnedSize and UnpinnedSizeChanged * Update events.md * polishing --- components/dockmanager/events.md | 23 ++++++++++++++++++++--- components/dockmanager/overview.md | 1 + 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/components/dockmanager/events.md b/components/dockmanager/events.md index aba596d3a..1ce9a6502 100644 --- a/components/dockmanager/events.md +++ b/components/dockmanager/events.md @@ -16,6 +16,7 @@ This article explains the events available in the Telerik DockManager for Blazor * [OnUndock](#ondock) * [VisibleChanged](#visiblechanged) * [SizeChanged](#sizechanged) +* [UnpinnedSizeChanged](#unpinnedsizechanged) * [OnPaneResize](#onpaneresize) * [State Events](#state-events) * [OnPin](#onpin) @@ -53,9 +54,13 @@ The `VisibleChanged` event is fired when the user tries to hide a given pane. Yo The `SizeChanged` event is triggered when the `Size` parameter of the corresponding pane is changed. +## UnpinnedSizeChanged + +The `UnpinnedSizeChanged` event is triggered when the `UnpinnedSize` parameter of the corresponding pane is changed. + ## OnPaneResize -The `OnPaneResize` event is fired when any pane is resized. It lets you respond to that change if needed - for example, call the `.Refresh()` method of a chart or otherwise repaint a child component in the content. You can also use it to, for example, update the saved [state](slug:dockmanager-state) for your users. +The `OnPaneResize` event is fired when a pane is resized, except unpinned panes. It lets you respond to that change if needed - for example, call the `.Refresh()` method of a chart or otherwise repaint a child component in the content. You can also use it to, for example, update the saved [state](slug:dockmanager-state) for your users. The event handler receives as an argument an `DockManagerPaneResizeEventArgs` object that contains: @@ -119,9 +124,13 @@ The event handler receives as an argument an `DockManagerUnpinEventArgs` object Pane 1. Undocking is allowed. Docking over it is cancelled. + UnpinnedSizeChanged is handled. + Current UnpinnedSize: @Pane1UnpinnedSize @@ -195,8 +204,9 @@ The event handler receives as an argument an `DockManagerUnpinEventArgs` object @code { - private TelerikDockManager DockManagerRef { get; set; } + private TelerikDockManager? DockManagerRef { get; set; } + private string Pane1UnpinnedSize { get; set; } = "360px"; private bool Pane4Visible { get; set; } = true; private bool FloatingPaneVisible { get; set; } = true; @@ -246,6 +256,13 @@ The event handler receives as an argument an `DockManagerUnpinEventArgs` object DockManagetEventLog.Insert(0, $"Pane {args.PaneId} was resized to {args.Size}."); } + private void Pane1UnpinnedSizeChanged(string newUnpinnedSize) + { + Pane1UnpinnedSize = newUnpinnedSize; + + DockManagetEventLog.Insert(0, $"Pane Pane 1 was resized to {newUnpinnedSize} while unpinned."); + } + private void OnPaneUnpin(DockManagerUnpinEventArgs args) { if (args.PaneId == "Pane4") @@ -282,4 +299,4 @@ The event handler receives as an argument an `DockManagerUnpinEventArgs` object ## See Also -* [DockManager Overview](slug:dockmanager-overview) \ No newline at end of file +* [DockManager Overview](slug:dockmanager-overview) diff --git a/components/dockmanager/overview.md b/components/dockmanager/overview.md index 64eb0507e..bfa6c429c 100644 --- a/components/dockmanager/overview.md +++ b/components/dockmanager/overview.md @@ -130,6 +130,7 @@ The following table lists the Dock Manager parameters. Also check the [DockManag | `Size` | `string` | Determines the size of the splitter pane. | | `Unpinnable` | `bool`
(`false`) | Determines whether the pane can be unpinned. | | `Unpinned` | `bool`
(`true`) | Determines whether the pane is unpinned. | +| `UnpinnedSize` | `string` | Determines the size of the splitter pane when it is unpinned. | | `Visible` | `bool`
(`true`) | Determines whether the tab/pane is rendered. | ### DockManagerSplitPane Parameters From 6109a08c0edd0789d88351d399f59c6ee0a9c514 Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 17:30:16 +0300 Subject: [PATCH 33/37] docs: Update PR-to-production action (#3025) * docs: Update PR-to-production action * add empty lines * Update .github/workflows/pull_request_closed.yml --- .github/workflows/pull_request_closed.yml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pull_request_closed.yml b/.github/workflows/pull_request_closed.yml index 7bdf9b920..0960834d2 100644 --- a/.github/workflows/pull_request_closed.yml +++ b/.github/workflows/pull_request_closed.yml @@ -1,15 +1,17 @@ name: Pull Request Closed + on: pull_request: branches: [master] types: [closed] + jobs: cherry_pick: if: ${{github.event.pull_request.merged == true}} runs-on: ubuntu-22.04 steps: - name: Should create PR to production? - uses: peter-evans/find-comment@v1 + uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e id: fc with: issue-number: ${{github.event.number}} @@ -39,7 +41,7 @@ jobs: echo "##[set-output name=branch;]$(echo ${BRANCH_NAME})" - name: Failed cherry-pick if: ${{ failure() }} - uses: peter-evans/create-or-update-comment@v1 + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 with: issue-number: ${{github.event.number}} body: | @@ -47,18 +49,14 @@ jobs: - name: pull-request id: pr if: steps.fc.outputs.comment-id != '' - uses: repo-sync/pull-request@v2 + uses: actions/checkout@v3 with: - destination_branch: "production" - source_branch: ${{ steps.cp.outputs.branch }} - github_token: ${{ secrets.GITHUB_TOKEN }} - pr_title: "Merge ${{ steps.cp.outputs.branch }} into production" - pr_body: | - *This is automatically generated PR* - PR from master branch: #${{github.event.number}}. Once the change is merged, upload the changes to LIVE. + token: '${{ secrets.GITHUB_TOKEN }}' + run: | + gh pr create --base production --head ${{ steps.cp.outputs.branch }} --title "Merge ${{ steps.cp.outputs.branch }} into production" --body "Automatically generated PR from master branch: #${{github.event.number}}. Once the change is merged, upload the changes to LIVE." - name: Post PR link if: steps.pr.outputs.pr_url != '' - uses: peter-evans/create-or-update-comment@v1 + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 with: issue-number: ${{github.event.number}} body: | From 3213c5c86c0d4d8f26884d1ffb457b3e0ac15cd0 Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 15:44:08 +0300 Subject: [PATCH 34/37] Use approved third-party action with a specific commit --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index ced11ef25..f94ca5313 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Create branch comment if: ${{ github.base_ref == 'master' && contains(join(github.event.pull_request.labels.*.name, ''), 'merge-to-production') }} - uses: peter-evans/create-or-update-comment@v1 + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 with: issue-number: ${{github.event.number}} body: | From ab9457846d8f745fe1e9bfca3876cab477fa044f Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 17:33:37 +0300 Subject: [PATCH 35/37] docs(Grid,TreeList): Add information about deleting items in edit mode (#3024) * docs(Grid): Add information about deleting items in edit mode * docs(TreeList): Add information about deleting items in edit mode --- components/grid/editing/incell.md | 2 ++ components/grid/editing/inline.md | 2 ++ components/grid/editing/overview.md | 9 +++++++-- components/treelist/editing/incell.md | 2 ++ components/treelist/editing/inline.md | 2 ++ components/treelist/editing/overview.md | 9 +++++++-- 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/components/grid/editing/incell.md b/components/grid/editing/incell.md index 570f0a1c3..07a8552ba 100644 --- a/components/grid/editing/incell.md +++ b/components/grid/editing/incell.md @@ -72,6 +72,8 @@ This section explains what happens when the user tries to perform another data o * If the validation is satisfied, then editing completes and the component fires `OnUpdate`. * If the validation is not satisfied, then editing aborts and the component fires `OnCancel`. +Deleting items that are currently in edit mode [fires `OnDelete` with a cloned data item instance](slug:grid-editing-overview#delete-operations). + ### Selection To enable [row selection](slug:grid-selection-row) with in-cell edit mode, use a [checkbox column](slug:components/grid/columns/checkbox). More information on that can be read in the [Row Selection](slug:grid-selection-row#selection-and-editing-modes) article. diff --git a/components/grid/editing/inline.md b/components/grid/editing/inline.md index 047e99ba5..96490aee5 100644 --- a/components/grid/editing/inline.md +++ b/components/grid/editing/inline.md @@ -54,6 +54,8 @@ This section explains what happens when the component is already in add or edit If the component is already in add or edit mode, and the user tries to perform another data operation, then editing aborts and the component fires `OnCancel`. +Deleting items that are currently in edit mode [fires `OnDelete` with a cloned data item instance](slug:grid-editing-overview#delete-operations). + ## Examples ### Basic diff --git a/components/grid/editing/overview.md b/components/grid/editing/overview.md index ead20360c..87a3cf9ff 100644 --- a/components/grid/editing/overview.md +++ b/components/grid/editing/overview.md @@ -35,6 +35,7 @@ The Grid CRUD operations rely on the following algorithm: Adding or editing rows in the Grid sets the following requirements on the Grid model: * The Grid model class must have a parameterless constructor. Otherwise, use the [Grid `OnModelInit` event](slug:grid-events#onmodelinit) to provide a data item instance [when the Grid needs to create one](#item-instances). Optinally, you can also [set some default values](slug://grid-kb-default-value-for-new-row). +* There must be a non-editable property that serves as a unique identifier. * All editable properties must be `public` and have setters. These properties must not be `readonly`. * All complex properties used in the Grid must be instantiated in the [Grid `OnModelInit` event](slug:grid-events#onmodelinit). * Self-referencing or inherited properties must not cause `StackOverflowException` or `AmbiguousMatchException` during [programmatic model instance creation](#item-instances). @@ -79,6 +80,8 @@ Delete operations provide the same user experience in all Grid edit modes and re Delete operations can work even if the Grid `EditMode` parameter value is `None`. +If the Grid contains Delete command buttons that display and operate in edit mode, these buttons will fire the [`OnDelete` event](#events) with a [cloned data item instance](#item-instances) in the [event argument](#gridcommandeventargs). To find the original data item in the Grid data source, use the item ID or [override the `Equals()` method of the Grid model class](slug://grid-kb-editing-in-hierarchy). + >tip See the delete operations in action in the complete examples for Grid [inline](slug:grid-editing-inline#examples), [in-cell](slug:grid-editing-incell#examples), and [popup](slug:grid-editing-popup#examples) editing. Also check how to [customize the Delete Confirmation Dialog](slug:grid-kb-customize-delete-confirmation-dialog). ## Commands @@ -97,7 +100,9 @@ Users execute commands in the following ways: * By clicking on editable cells in [in-cell edit mode](slug:grid-editing-incell) and then anywhere else on the page. * By using the [Grid keyboard navigation](https://demos.telerik.com/blazor-ui/grid/keyboard-navigation). -Command buttons can only reside in a [Grid Command Column](slug:components/grid/columns/command) or the [Grid ToolBar](slug:components/grid/features/toolbar). You can also [trigger add and edit operations programmatically](slug:grid-kb-add-edit-state) from anywhere on the web page through the [Grid State](slug:grid-state). +Command buttons can only reside in a [Grid Command Column](slug:components/grid/columns/command) or the [Grid ToolBar](slug:components/grid/features/toolbar). Each command button in the command column is visible only in display mode or only in edit mode, depending on the button's `ShowInEdit` boolean parameter value. + +You can also [trigger add and edit operations programmatically](slug:grid-kb-add-edit-state) from anywhere on the web page through the [Grid State](slug:grid-state). ## Events @@ -110,7 +115,7 @@ The following table describes the Grid events, which are related to adding, dele | `OnAdd` | No | Fires on `Add` [command button](slug://components/grid/columns/command) click, before the Grid enters add mode. This event preceeds `OnCreate` or `OnCancel`. | [New](#item-instances) | Grid remains in read mode. | | `OnCancel` | No | Fires on `Cancel` command invocation. | [New or cloned](#item-instances) | Grid remains in add or edit mode. | | `OnCreate` | To add new items. | Fires on `Save` command invocation for new items. This event succeeds `OnAdd`. | [New](#item-instances) | Grid remains in add mode. | -| `OnDelete` | To [delete items](#delete-operations). | Fires on `Delete` command button click. | Original | Grid won't rebind. Deletion depends on the app itself. | +| `OnDelete` | To [delete items](#delete-operations). | Fires on `Delete` command button click. | [Original or cloned](#item-instances) | Grid won't rebind. Deletion depends on the app itself. | | `OnEdit` | No | Fires on `Edit` command invocation, before the Grid actually enters edit mode. This event preceeds `OnUpdate` or `OnCancel`. | Original | Grid remains in read mode. | | `OnModelInit` | [Depends on the Grid model type](slug:grid-events#onmodelinit) | Fires when the Grid requires a [new model instance](#item-instances), which is immediately before `OnAdd` or immediately after `OnEdit`.
Use this event when the Grid model type is an [interface, abstract class, or has no parameterless constructor](slug:grid-events#onmodelinit). | No event arguments | Not cancellable | | `OnUpdate` | To edit existing items. | Fires on `Save` command invocation for existing items. This event succeeds `OnEdit`. | [Cloned](#item-instances) | Grid remains in edit mode. | diff --git a/components/treelist/editing/incell.md b/components/treelist/editing/incell.md index 105f32563..532e33ccd 100644 --- a/components/treelist/editing/incell.md +++ b/components/treelist/editing/incell.md @@ -72,6 +72,8 @@ This section explains what happens when the user tries to perform another data o * If the validation is satisfied, then editing completes and the component fires `OnUpdate`. * If the validation is not satisfied, then editing aborts and the component fires `OnCancel`. +Deleting items that are currently in edit mode [fires `OnDelete` with a cloned data item instance](slug:treelist-editing-overview#delete-operations). + ### Selection To enable [row selection](slug:treelist-selection-row) with in-cell edit mode, use a [checkbox column](slug:treelist-columns-checkbox). More information on that can be read in the [Row Selection](slug:treelist-selection-row#selection-and-editing-modes) article. diff --git a/components/treelist/editing/inline.md b/components/treelist/editing/inline.md index c3179862a..049e007cc 100644 --- a/components/treelist/editing/inline.md +++ b/components/treelist/editing/inline.md @@ -54,6 +54,8 @@ This section explains what happens when the component is already in add or edit If the component is already in add or edit mode, and the user tries to perform another data operation, then editing aborts and the component fires `OnCancel`. +Deleting items that are currently in edit mode [fires `OnDelete` with a cloned data item instance](slug:treelist-editing-overview#delete-operations). + ## Example The example below shows how to: diff --git a/components/treelist/editing/overview.md b/components/treelist/editing/overview.md index 30d3d38ca..def09dfe6 100644 --- a/components/treelist/editing/overview.md +++ b/components/treelist/editing/overview.md @@ -35,6 +35,7 @@ The TreeList CRUD operations rely on the following algorithm: Adding or editing rows in the TreeList sets the following requirements on the TreeList model: * The TreeList model class must have a parameterless constructor. Otherwise, use the [TreeList `OnModelInit` event](slug:treelist-events#onmodelinit) to provide a data item instance [when the TreeList needs to create one](#item-instances). Optinally, you can also [set some default values](slug://grid-kb-default-value-for-new-row). +* There must be a non-editable property that serves as a unique identifier. * All editable properties must be `public` and have setters. These properties must not be `readonly`. * Self-referencing or inherited properties must not cause `StackOverflowException` or `AmbiguousMatchException` during [programmatic model instance creation](#item-instances). @@ -78,6 +79,8 @@ Delete operations provide the same user experience in all TreeList edit modes an Delete operations can work even if the TreeList `EditMode` parameter value is `None`. +If the TreeList contains Delete command buttons that display and operate in edit mode, these buttons will fire the [`OnDelete` event](#events) with a [cloned data item instance](#item-instances) in the [event argument](#treelistcommandeventargs). To find the original data item in the TreeList data source, use the item ID or [override the `Equals()` method of the TreeList model class](slug:grid-kb-save-load-state-localstorage). + >tip See the delete operations in action in the complete examples for TreeList [inline](slug:treelist-editing-inline#example), [in-cell](slug:treelist-editing-incell#example) and [popup](slug:treelist-editing-popup#example) editing. Also check how to [customize the Delete Confirmation Dialog](slug:grid-kb-customize-delete-confirmation-dialog). ## Commands @@ -96,7 +99,9 @@ Users execute commands in the following ways: * By clicking on editable cells in [in-cell edit mode](slug:treelist-editing-incell) and then anywhere else on the page. * By using the [TreeList keyboard navigation](https://demos.telerik.com/blazor-ui/treelist/keyboard-navigation). -Command buttons can only reside in a [TreeList Command Column](slug:treelist-columns-command) or the [TreeList ToolBar](slug:treelist-toolbar). You can also [trigger add and edit operations programmatically](slug:grid-kb-add-edit-state) from anywhere on the web page through the [TreeList State](slug:treelist-state). +Command buttons can only reside in a [TreeList Command Column](slug:treelist-columns-command) or the [TreeList ToolBar](slug:treelist-toolbar). Each command button in the command column is visible only in display mode or only in edit mode, depending on the button's `ShowInEdit` boolean parameter value + +You can also [trigger add and edit operations programmatically](slug:grid-kb-add-edit-state) from anywhere on the web page through the [TreeList State](slug:treelist-state). ## Events @@ -109,7 +114,7 @@ The following table describes the TreeList events, which are related to adding, | `OnAdd` | No | Fires on `Add` [command button](slug://treelist-columns-command) click, before the TreeList enters add mode. This event preceeds `OnCreate` or `OnCancel`. | [New](#item-instances) | TreeList remains in read mode. | | `OnCancel` | No | Fires on `Cancel` command invocation. | [New or cloned](#item-instances) | TreeList remains in add or edit mode. | | `OnCreate` | To add new items. | Fires on `Save` command invocation for new items. This event succeeds `OnAdd`. | [New](#item-instances) | TreeList remains in add mode. | -| `OnDelete` | To [delete items](#delete-operations). | Fires on `Delete` command button click. | Original | TreeList won't rebind. Deletion depends on the app itself. | +| `OnDelete` | To [delete items](#delete-operations). | Fires on `Delete` command button click. | [Original or cloned](#item-instances) | TreeList won't rebind. Deletion depends on the app itself. | | `OnEdit` | No | Fires on `Edit` command invocation, before the TreeList actually enters edit mode. This event preceeds `OnCreate` or `OnCancel`. | Original | TreeList remains in read mode. | | `OnModelInit` | [Depends on the TreeList model type](slug:treelist-events#onmodelinit) | Fires when the TreeList requires a [new model instance](#item-instances), which is immediately before `OnAdd` or immediately after `OnEdit`.
Use this event when the TreeList model type is an [interface, abstract class, or has no parameterless constructor](slug:treelist-events#onmodelinit). | No event arguments | Not cancellable | | `OnUpdate` | To edit existing items. | Fires on `Save` command invocation for existing items. This event succeeds `OnEdit`. | [Cloned](#item-instances) | TreeList remains in edit mode. | From 9371096ed88addfe7fe3bca4c492cb11ffb1c047 Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 17:45:20 +0300 Subject: [PATCH 36/37] docs(ButtonGroup): Add more examples to Buttons page (#3021) --- components/buttongroup/buttons.md | 111 +++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 16 deletions(-) diff --git a/components/buttongroup/buttons.md b/components/buttongroup/buttons.md index 5e446dd68..019739554 100644 --- a/components/buttongroup/buttons.md +++ b/components/buttongroup/buttons.md @@ -10,12 +10,45 @@ position: 5 # ButtonGroup Buttons -The ButtonGroup component supports two types of buttons that have different behavior: +The ButtonGroup component supports two types of buttons that have different behaviors: -* [`ButtonGroupToggleButton`](#buttongroup-togglebutton) * [`ButtonGroupButton`](#buttongroup-button) +* [`ButtonGroupToggleButton`](#buttongroup-togglebutton) + +You can add the desired button instances by declaring the dedicated button tags. Additionally, you can individually configure their [appearance](slug:buttongroup-appearance), [enabled/disabled state](#disabled-state) and [visibility](#visibility) through the parameters of each button tag. + +## ButtonGroup Button + +The `ButtonGroupButton` does not change its visual state when clicked. It behaves as a regular button and does not support selection. + +The `ButtonGroupButton` inherits the parameters and behavior of the [Telerik UI for Blazor Button](slug:components/button/overview) component. + +>caption Using Buttons in a group + +````RAZOR + + Button 1 + Button 2 + Button 3 + -You can add the desired button instances by declaring the dedicated button tags. Additionally, you can individually configure their [appearance](slug:buttongroup-appearance), [enabled/disabled state](#disabled-state) and [visibility](#visibility) through the parameters each button tag exposes. +@code { + private void OnButton1Click() + { + // ... + } + + private void OnButton2Click() + { + // ... + } + + private void OnButton3Click() + { + // ... + } +} +```` ## ButtonGroup ToggleButton @@ -23,11 +56,39 @@ The `ButtonGroupToggleButton` becomes selected when clicked and deselects when a The `ButtonGroupToggleButton` inherits the parameters and behavior of the [`TelerikToggleButton`](slug:togglebutton-overview) component. -## ButtonGroup Button +>caption Using ToogleButtons in a group -The `ButtonGroupButton` does not change its visual state when clicked. It behaves as a regular button and does not support selection. +````RAZOR + + Toggle Button 1 + Toggle Button 2 + Toggle Button 3 + -The `ButtonGroupButton` inherits the parameters and behavior of the [Telerik UI for Blazor Button](slug:components/button/overview) component. +@code { + private bool ToggleButton1Selected { get; set; } = true; + private bool ToggleButton2Selected { get; set; } + private bool ToggleButton3Selected { get; set; } + + private void OnToggleButton1Click() + { + // ... + } + + private void OnToggleButton2Click() + { + // ... + } + + private void OnToggleButton3Click() + { + // ... + } +} +```` ## Disabled State @@ -37,13 +98,18 @@ To disable a button, set its `Enabled` attribute to `false`. ````RAZOR - Enabled - Disabled - Enabled - Disabled + Enabled Button + Disabled Button + Enabled ToggleButton + Enabled ToggleButton + Disabled ToggleButton -```` +@code { + private bool ToggleButton1Selected { get; set; } = true; + private bool ToggleButton2Selected { get; set; } +} +```` ## Visibility @@ -53,13 +119,26 @@ You can set the `Visible` parameter of individual buttons to `false` to hide the ````RAZOR - First - Hidden - Third - Fourth + Button + Button Hidden + ToggleButton + ToggleButton Hidden + +
+
+ +Show Hidden Buttons + +@code { + private bool ShowHiddenButtons { get; set; } + + private bool ToggleButton1Selected { get; set; } = true; + private bool ToggleButton2Selected { get; set; } +} ```` ## See Also - * [Live Demo: Button Types](https://demos.telerik.com/blazor-ui/buttongroup/button-types) \ No newline at end of file + * [Live Demo: Button Types](https://demos.telerik.com/blazor-ui/buttongroup/button-types) From 47991a4132dff9f51d800a2a50b2054c2ba4e18a Mon Sep 17 00:00:00 2001 From: Dimo Dimov <961014+dimodi@users.noreply.github.com> Date: Fri, 13 Jun 2025 17:45:30 +0300 Subject: [PATCH 37/37] docs(QRCode): Improve Size and border Width documentation (#3023) --- components/barcodes/qrcode/overview.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/components/barcodes/qrcode/overview.md b/components/barcodes/qrcode/overview.md index 69e97a3d0..1ce01892c 100644 --- a/components/barcodes/qrcode/overview.md +++ b/components/barcodes/qrcode/overview.md @@ -16,19 +16,16 @@ The generated image from the component is a machine-readable label that contains ## Creating Blazor QRCode -1. Add the `TelerikQRCode` tag to add the component to your razor page. +1. Use the `TelerikQRCode` tag to add the component to your razor page. +1. Set the `Value` parameter, according to the [encoding recommendations](slug:qrcode-encoding). +1. Set the `Size` parameter, depending on the expected scanning distance and the required data capacity. +1. (optional) Define a [QRCode overlay type](slug:qrcode-qr-code-types)). -1. Set the `Value` property. - -1. Set its `Size` property. - -1. Optionally, choose a `QRCode Type` (one of the [types we support](slug:qrcode-qr-code-types)). - ->caption A basic configuration of the Telerik QRCode +>caption Basic Telerik QRCode ````RAZOR - + ```` @@ -58,7 +55,7 @@ The Blazor Barcode provides various parameters that allow you to configure the c | `QRCodeEncoding` | `enum` | The encoding mode used to encode the value. | | `QRCodeErrorCorrection` | `enum` | The error correction level used to encode the value. | | `Value` | `string` | Defines the initial value of the QRCode. | -| `Size` | `string` | Specifies the size (`Width` and `Height`) of a QR code in pixels (i.e. "200px") as the QRCode is a square. You can read more details for the dimension properties in the [Dimensions article](slug:common-features/dimensions). Setting both `Size` and `Width` and/or `Height` will throw an error. Setting different values to `Width` and `Height` will also cause an issue. | +| `Size` | `string` | Specifies the size (`Width` and `Height`) of a QR code in pixels (i.e. "200px") as the QRCode is a square. You can read more details for the dimension properties in the [Dimensions article](slug:common-features/dimensions). Setting both `Size` and `Width` and/or `Height` will throw an error. Setting different values to `Width` and `Height` will also cause an issue. To set an optimal `Size`, consider the expected scanning distance and data capacity. | | `Width` | `string` | Sets the width of the QRCode. If `Height` is set and the `Size` property is not set, the same value as `Width` should be set to `Height`. | | `Height` | `string` | Sets the height of the QRCode. If `Height` is set and the `Size` property is not set, the same value as `Height` should be set to `Width`. | | `Class` | `string` | The CSS class that will be rendered on the main wrapping element of the QRCode component. | @@ -84,7 +81,7 @@ The nested `QRCodeBorder` tag exposes parameters that enable you to customize th | Parameter | Type | Description | | ----------- | ----------- | ----------- | | `Color` | `string` | The color of the border. Accepts a valid CSS color string, including HEX and RGB. | -| `Width` | `double` | The width of the border in pixels. By default the border width is set to zero which means that the border will not be visible. | +| `Width` | `double` | The width of the border in pixels. The default value is `0` and the border is not visible. The QR Code border is part of the component `Size`. Thus, a wider border may require a larger `Size`. | ## Next Steps