diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000000..eb5cfec430 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,552 @@ +# Blazor Code Style Guide + +This guide outlines best practices for Razor component development and documentation in Blazor. + +## Razor File Structure + +Use the following top-down order in `.razor` files: + +1. `@page` +2. `@using` +3. `@namespace` +4. `@inherits` +5. `@implements` +6. `@inject` + +Insert ` + +@code { + private CompositeFilterDescriptor Value { get; set; } = new CompositeFilterDescriptor(); + private string EventMessage { get; set; } = string.Empty; + + private void OnFilterUpdate() + { + EventMessage = $"Filter updated at {DateTime.Now:HH:mm:ss}"; + } + + public class Person + { + public int EmployeeId { get; set; } + public string Name { get; set; } = string.Empty; + public int AgeInYears { get; set; } + } +} +```` + ## ValueChanged The `ValueChanged` event fires when the value has changed. Its event handler receives the updated `CompositeFilterDescriptor` as an argument. ->caption Handle ValueChanged. +> The `ValueChanged` event is deprecated and will be removed in future versions. Use the `OnUpdate` event instead. + +>caption Handle ValueChanged ````RAZOR @* This code snippet showcases an example of how to handle the ValueChanged event. *@ diff --git a/components/form/formgroups.md b/components/form/formgroups.md index 5ff7da282c..5919bfc08b 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 - + diff --git a/components/form/overview.md b/components/form/overview.md index 57643d1715..989fe67a82 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 diff --git a/components/form/validation.md b/components/form/validation.md index 81d5171fb5..f092d624ff 100644 --- a/components/form/validation.md +++ b/components/form/validation.md @@ -133,7 +133,6 @@ You can use the built-in `DataAnnotationsValidator` that comes with the Blazor f - @code { public Person person { get; set; } = new Person(); @@ -158,8 +157,7 @@ You can use the -````RAZOR +````RAZOR.skip-repl @using System.Dynamic @using System.ComponentModel.DataAnnotations @@ -228,50 +226,122 @@ When using a model with nested objects and fields, specify their `Field` setting ### Fluent Validation -You can use third-party validation libraries that integrate with the standard `EditContext` such as FluentValidation together with the Telerik Form for Blazor. +You can use third-party validation libraries that integrate with the standard `EditContext` such as [FluentValidation](https://fluentvalidation.net/) together with the Telerik Form for Blazor. ->note Such third party tools are not included with the Telerik UI for Blazor package. Your project must reference their NuGet packages explicitly. The code snippet below will not run unless you install the an appropriate package first. You can find some in their official documentation. +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 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 -
-````RAZOR -@using Microsoft.AspNetCore.Components.Forms -@using FluentValidation +````RAZOR Home.razor @using Blazored.FluentValidation +@using FluentValidation -
- - - - - -
+ + + + + + + + + + + + + + + + + +

@FormSubmitResult

@code { - public EditContext EditContext {get; set; } - public Customer MyModel { get; set; } = new Customer(); - public CustomerValidator Validator { get; set; } = new CustomerValidator(); + private Person PersonToEdit { get; set; } = new(); + + public PersonValidator PersonFluentValidator { get; set; } = new(); - protected override void OnInitialized() + private string FormSubmitResult { get; set; } = string.Empty; + + private void LastNameChanged(string newLastName) { - EditContext = new EditContext(MyModel); - base.OnInitialized(); + PersonToEdit.LastName = newLastName; } - public class Customer + private void OnFormValidSubmit() { - public string FirstName { get; set; } - public string LastName { get; set; } + FormSubmitResult = $"Form Submit Success at {DateTime.Now.ToString("HH:mm:ss")}"; + } + + public class PersonValidator : AbstractValidator + { + public PersonValidator() + { + RuleFor(customer => customer.FirstName).NotEmpty().MinimumLength(2).MaximumLength(60); + RuleFor(customer => customer.MiddleName).NotEmpty().MaximumLength(60); + RuleFor(customer => customer.LastName).NotEmpty().MinimumLength(2).MaximumLength(60); + } + } + + public class Person + { + public int Id { get; set; } + + public string FirstName { get; set; } = string.Empty; + + public string MiddleName { get; set; } = string.Empty; + + public string LastName { get; set; } = string.Empty; } +} +```` +````RAZOR TextBox.razor +@using System.Linq.Expressions + + + +@code { + [Parameter] + public string Value { get; set; } = string.Empty; + + [Parameter] + public EventCallback ValueChanged { get; set; } + + [Parameter] + public Expression>? ValueExpression { get; set; } - public class CustomerValidator : AbstractValidator + [Parameter] + public string Id { get; set; } = string.Empty; + + private async Task TextBoxValueChanged(string newValue) { - public CustomerValidator() + Value = newValue; + + if (ValueChanged.HasDelegate) { - RuleFor(customer => customer.FirstName).NotEmpty().MaximumLength(50); - RuleFor(customer => customer.LastName).NotEmpty().MaximumLength(50); + await ValueChanged.InvokeAsync(newValue); } } } diff --git a/components/gantt/gantt-tree/editing/incell.md b/components/gantt/gantt-tree/editing/incell.md index a1b3e9d3ba..96e93d5a74 100644 --- a/components/gantt/gantt-tree/editing/incell.md +++ b/components/gantt/gantt-tree/editing/incell.md @@ -18,10 +18,18 @@ Command columns and non-editable columns are skipped while tabbing. The InCell edit mode provides a specific user experience and behaves differently than other edit modes. Please review the notes below to get a better understanding of these specifics. +## New Row Position + +To control whether a newly added item appears at the top or bottom of the Gantt Tree, set the `NewRowPosition` parameter. + +The `NewRowPosition` parameter accepts values from the `GanttTreeListNewRowPosition` enum: + +- `Top` (default)—Inserts the new item at the top of the view. +- `Bottom`—Inserts the new item at the bottom of the view. + ### Note It is up to the data access logic to save the data once it is changed in the data collection, or to revert changes. The example above showcases the events that allow you to do that. In a real application, the code for handling data operations may be entirely different. - >caption InCell Editing Example. ````RAZOR @@ -68,20 +76,9 @@ It is up to the data access logic to save the data once it is changed in the dat @code { - public DateTime SelectedDate { get; set; } = new DateTime(2019, 11, 11, 6, 0, 0); - - class FlatModel - { - public int Id { get; set; } - public int? ParentId { get; set; } - public string Title { get; set; } - public double PercentComplete { get; set; } - public DateTime Start { get; set; } - public DateTime End { get; set; } - } - - public int LastId { get; set; } = 1; - List Data { get; set; } + private DateTime SelectedDate { get; set; } = new DateTime(2019, 11, 11, 6, 0, 0); + private int LastId { get; set; } = 1; + private List Data { get; set; } protected override void OnInitialized() { @@ -122,6 +119,16 @@ It is up to the data access logic to save the data once it is changed in the dat base.OnInitialized(); } + public class FlatModel + { + public int Id { get; set; } + public int? ParentId { get; set; } + public string Title { get; set; } + public double PercentComplete { get; set; } + public DateTime Start { get; set; } + public DateTime End { get; set; } + } + private async Task CreateItem(GanttCreateEventArgs args) { var argsItem = args.Item as FlatModel; @@ -251,4 +258,3 @@ It is up to the data access logic to save the data once it is changed in the dat ## See Also * [Live Demo: Gantt InCell Editing](https://demos.telerik.com/blazor-ui/gantt/editing-incell) - diff --git a/components/gantt/gantt-tree/editing/inline.md b/components/gantt/gantt-tree/editing/inline.md index 55ca17ea03..690e11689c 100644 --- a/components/gantt/gantt-tree/editing/inline.md +++ b/components/gantt/gantt-tree/editing/inline.md @@ -20,6 +20,14 @@ You can also cancel the events by setting the `IsCancelled` property of the even To enable Inline editing in the Gantt Tree, set its `TreeListEditMode` property to `GanttTreeListEditMode.Inline`, then handle the CRUD events as shown in the example below. +## New Row Position + +To control whether a newly added item appears at the top or bottom of the Gantt Tree, set the `NewRowPosition` parameter. + +The `NewRowPosition` parameter accepts values from the `GanttTreeListNewRowPosition` enum: + +- `Top` (default)—Inserts the new item at the top of the view. +- `Bottom`—Inserts the new item at the bottom of the view. >caption The Command buttons and the Gantt events let you handle data operations in Inline edit mode. @@ -70,20 +78,9 @@ To enable Inline editing in the Gantt Tree, set its `TreeListEditMode` property @code { - public DateTime SelectedDate { get; set; } = new DateTime(2019, 11, 11, 6, 0, 0); - - class FlatModel - { - public int Id { get; set; } - public int? ParentId { get; set; } - public string Title { get; set; } - public double PercentComplete { get; set; } - public DateTime Start { get; set; } - public DateTime End { get; set; } - } - - public int LastId { get; set; } = 1; - List Data { get; set; } + private DateTime SelectedDate { get; set; } = new DateTime(2019, 11, 11, 6, 0, 0); + private int LastId { get; set; } = 1; + private List Data { get; set; } protected override void OnInitialized() { @@ -124,6 +121,16 @@ To enable Inline editing in the Gantt Tree, set its `TreeListEditMode` property base.OnInitialized(); } + public class FlatModel + { + public int Id { get; set; } + public int? ParentId { get; set; } + public string Title { get; set; } + public double PercentComplete { get; set; } + public DateTime Start { get; set; } + public DateTime End { get; set; } + } + private async Task CreateItem(GanttCreateEventArgs args) { var argsItem = args.Item as FlatModel; diff --git a/components/gantt/gantt-tree/editing/overview.md b/components/gantt/gantt-tree/editing/overview.md index b25d18813b..deacf14f0c 100644 --- a/components/gantt/gantt-tree/editing/overview.md +++ b/components/gantt/gantt-tree/editing/overview.md @@ -298,6 +298,30 @@ You can customize the editors rendered in the Gantt Tree by providing the `Edito * `IsCanceled`- a boolean field indicating whether the operation is to be prevented. +## New Row Position + +You can control whether a newly added item appears at the top or bottom of the Gantt Tree. Use the [`NewRowPosition`](https://www.telerik.com/blazor-ui/documentation/api/telerik.blazor.gantttreelistnewrowposition) parameter to specify the position. This parameter does not affect Popup edit mode, which always displays a dialog for new items. + +This configuration is available in InCell and Inline edit modes. For more details, see the [Tree InCell Editing](slug:gant-tree-incell-editing#new-row-position) and [Tree Inline Editing](slug:gant-tree-inline-editing#new-row-position) articles. + +> When you set `NewRowPosition` to `Bottom`, add the new item at the end of your data collection in the `OnCreate` event handler. When set to `Top`, insert the new item at the beginning of the collection. This ensures the new row appears in the correct position in the view after successfully creating the new record. + +>caption Example of adding a new item to the Gantt based on the `NewRowPosition` value + +
+````C# +private void OnCreate(GanttCreateEventArgs args) +{ + if (NewRowPosition == GanttTreeListNewRowPosition.Bottom) + { + dataCollection.Add(newItem); + } + else // Top + { + dataCollection.Insert(0, newItem); + } +} +```` ## Example diff --git a/components/gauges/arc/labels.md b/components/gauges/arc/labels.md index 48ece6bda1..0455af3ed6 100644 --- a/components/gauges/arc/labels.md +++ b/components/gauges/arc/labels.md @@ -13,13 +13,10 @@ position: 20 You can customize the appearance of the labels rendered on the [scale](slug:arc-gauge-scale) of the Arc Gauge by using the ``, child tag of the ``, and the parameters it exposes: * [Format](#format) - * [Center Template](#center-template) - +* [Position](#position) * [Color](#color) - * [Visible](#visible) - * [Additional Customization](#additional-customization) ## Format @@ -87,6 +84,42 @@ The center template allows you to take control of the rendering of the central s ```` +## Position + +The `Position` parameter is of enum type `ArcGaugeScaleLabelsPosition` and determines whether the Gauge labels are on the inside (default) or outside of the Gauge graphic. Labels on the inside allow for a visually larger component within the same available space. + +>caption Setting Arc Gauge label position + +````RAZOR + + + + + + + + + + + + + + + + + + + + + + + + + +```` + ## Color The `Color` (`string`) parameter controls the color of the labels. It accepts **CSS**, **HEX** and **RGB** colors. diff --git a/components/gauges/circular/labels.md b/components/gauges/circular/labels.md index d5eca523e7..5551dc9714 100644 --- a/components/gauges/circular/labels.md +++ b/components/gauges/circular/labels.md @@ -13,13 +13,10 @@ position: 15 You can customize the appearance of the labels rendered on the [scale](slug:circular-gauge-scale) of the Circular Gauge by using the ``, child tag of the ``, and the parameters it exposes: * [Format](#format) - * [Center Template](#center-template) - +* [Position](#position) * [Color](#color) - * [Visible](#visible) - * [Additional Customization](#additional-customization) ## Format @@ -91,6 +88,42 @@ The center template allows you to take control of the rendering of the central s ```` +## Position + +The `Position` parameter is of enum type `CircularGaugeScaleLabelsPosition` and determines whether the Gauge labels are on the inside (default) or outside of the Gauge graphic. Labels on the inside allow for a visually larger component on the same available space. + +>caption Setting Circular Gauge label position + +````RAZOR + + + + + + + + + + + + + + + + + + + + + + + + + +```` + ## Color The `Color` (`string`) parameter controls the color of the labels. It accepts **CSS**, **HEX** and **RGB** colors. diff --git a/components/grid/editing/incell.md b/components/grid/editing/incell.md index 570f0a1c36..b4dd5155e2 100644 --- a/components/grid/editing/incell.md +++ b/components/grid/editing/incell.md @@ -54,6 +54,17 @@ In in-cell edit mode, the `OnAdd` and `OnCreate` events fire immediately one aft The above algorithm is different from [inline](slug:grid-editing-inline) and [popup](slug:grid-editing-popup) editing where new rows are only added to the data source after users populate them with valid values. +## New Row Position + +You can control whether a newly added item appears at the top or bottom of the Grid. Use the `NewRowPosition` parameter to specify the position. + +The `NewRowPosition` parameter accepts values from the `GridNewRowPosition` enum: + +- `Top` (default)—Inserts the new item at the top of the view. +- `Bottom`—Inserts the new item at the bottom of the view. + +For a complete example of how this feature works, see the following [example](slug:grid-editing-incell#basic). + ## Integration with Other Features Here is how the component behaves when the user tries to use add and edit operations together with other component features. Also check the [common information on this topic for all edit modes](slug:grid-editing-overview#integration-with-other-features). @@ -72,6 +83,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 047e99ba57..a8022b2902 100644 --- a/components/grid/editing/inline.md +++ b/components/grid/editing/inline.md @@ -37,7 +37,16 @@ Inline add, edit, and delete operations use the following [command buttons](slug In inline edit mode, the Grid commands execute row by row and the corresponding [Grid events](slug:grid-editing-overview#events) also fire row by row. This is similar to [popup editing](slug:grid-editing-popup) and unlike [in-cell editing](slug:grid-editing-incell), where commands and events relate to cells. -When validation is not satisfied, clicking the **Save**, **Delete** or **Add** command buttons has no effect, but users can still navigate between all input components in the row to complete the editing. +When validation is not satisfied, clicking the **Save**, **Delete** or **Add** command buttons have no effect, but users can still navigate between all input components in the row to complete the editing. + +## New Row Position + +You can control whether a newly added item appears at the top or bottom of the Grid. Use the `NewRowPosition` parameter to specify the position. + +The `NewRowPosition` parameter accepts values from the `GridNewRowPosition` enum: + +- `Top` (default)—Inserts the new item at the top of the view. +- `Bottom`—Inserts the new item at the bottom of the view. ## Integration with Other Features @@ -54,6 +63,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 ead20360ca..02f76a10e7 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. | @@ -200,6 +205,32 @@ When editing a master row in a [hierarchy Grid](slug://components/grid/features/ Learn more integration details for the [inline](slug:grid-editing-inline#integration-with-other-features) and [in-cell](slug:grid-editing-incell#integration-with-other-features) edit modes. + +## New Row Position + +You can control whether a newly added item appears at the top or bottom of the Grid. Use the [`NewRowPosition`](https://www.telerik.com/blazor-ui/documentation/api/telerik.blazor.gridnewrowposition) parameter to specify the position. This parameter does not affect Popup edit mode, which always displays a dialog for new items. + +This configuration is available in InCell and Inline edit modes. For more details, see the [InCell Editing](slug:grid-editing-incell#new-row-position) and [Inline Editing](slug:grid-editing-inline#new-row-position) articles. + +> When you set `NewRowPosition` to `Bottom`, add the new item at the end of your data collection in the `OnCreate` event handler. When set to `Top`, insert the new item at the beginning of the collection. This ensures the new row appears in the correct position in the view after successfully creating the new record. + +>caption Example of adding a new item to the Grid based on the `NewRowPosition` value + +
+````C# +private void OnCreate(GridCommandEventArgs args) +{ + if (NewRowPosition == GridNewRowPosition.Bottom) + { + dataCollection.Add(newItem); + } + else // Top + { + dataCollection.Insert(0, newItem); + } +} +```` + ## Examples See Grid CRUD operations in action at: diff --git a/components/grid/highlighting.md b/components/grid/highlighting.md new file mode 100644 index 0000000000..84b09f5729 --- /dev/null +++ b/components/grid/highlighting.md @@ -0,0 +1,116 @@ +--- +title: Highlighting +page_title: Grid Highlighting +slug: grid-highlighting +description: Highlight rows and cells in the Telerik Blazor Grid to draw attention to important data. +tags: telerik,blazor,grid,highlight,highlighting +published: true +position: 40 +--- + +# Blazor Grid Highlighting + +The Telerik Blazor Grid enables you to highlight rows and cells programmatically. Use highlighting to draw attention to important data, indicate status, or visually group related records. Highlighting does not require user interaction and is fully controlled by the application logic. + +## Key Features + +* Highlight entire rows by providing a list of data items. +* Highlight individual cells by specifying the data item and column. +* Combine row and cell highlighting. +* Highlighting uses a visual style similar to selection, but does not affect selection state or user interaction. + +To see the Grid highlighting in action, check the below [example](#example). + +## API Reference + +The Grid highlighting feature exposes the following parameters: + +- `HighlightedItems`—Highlight entire rows by providing the data items to highlight. The list must contain references to items from the grid's data source, not new instances. +- `HighlightedCells`—Highlight individual cells by specifying both the data item and the column field. Both values must match the Grid data and column definitions. + +See [Grid Highlighting API Reference](slug:telerik.blazor.components.gridhighlighting) for details about these parameters and the `GridHighlightedCellDescriptor` type. + +## Example + +>caption Example of highlighting rows and cells in the Blazor Grid + +````RAZOR + + + + + + + + + + + +@code { + private List GridData { get; set; } = new(); + private List HighlightedItems { get; set; } = new(); + private List HighlightedCells { get; set; } = new(); + + protected override void OnInitialized() + { + GenerateData(); + SetHighlight(); + } + + private void SetHighlight() + { + // Highlight 5 items starting from the 3rd item in the data list + HighlightedItems = GridData.Skip(2).Take(5).ToList(); + + // Highlight specific cells: the ProductName of the first item and Discounted of the second item + HighlightedCells = new List + { + new GridHighlightedCellDescriptor + { + ColumnField = nameof(Product.ProductName), + DataItem = GridData[0] + }, + new GridHighlightedCellDescriptor + { + ColumnField = nameof(Product.Discontinued), + DataItem = GridData[1] + } + }; + } + + private void GenerateData() + { + var random = new Random(); + for (int i = 1; i <= 20; i++) + { + GridData.Add(new Product + { + ProductId = i, + ProductName = $"Product {i}", + UnitPrice = Math.Round(random.NextDouble() * 100, 2), + UnitsInStock = random.Next(1, 100), + CreatedAt = DateTime.Now.AddDays(-random.Next(1, 100)), + Discontinued = i % 5 == 0 + }); + } + } + + public class Product + { + public int ProductId { get; set; } + public string ProductName { get; set; } = string.Empty; + public double UnitPrice { get; set; } + public int UnitsInStock { get; set; } + public DateTime CreatedAt { get; set; } + public bool Discontinued { get; set; } + } +} +```` + +## See Also + +* [Grid Selection](slug:grid-selection-overview) +* [Highlighting API Reference](slug:telerik.blazor.components.gridhighlighting) \ No newline at end of file diff --git a/components/grid/overview.md b/components/grid/overview.md index 1fdb9de86b..ff65765d96 100644 --- a/components/grid/overview.md +++ b/components/grid/overview.md @@ -5,6 +5,7 @@ description: The Blazor Grid provides a comprehensive set of ready-to-use featur slug: grid-overview tags: telerik,blazor,grid,datagrid,overview published: True +hideCta: True position: 0 --- @@ -12,6 +13,8 @@ position: 0 This article provides a quick introduction to get your first Blazor data grid component up and running in a few seconds. There is a video tutorial and a list of the key features. +ninja-iconTired of reading docs? With our new AI Coding Assistants, you can add, configure, and troubleshoot Telerik UI for Blazor components—right inside your favorite AI-powered IDE: Visual Studio, VS Code, Cursor, and more. Start building faster, smarter, and with contextual intelligence powered by our docs/APIs:Try AI Assistants + The Telerik Blazor Data Grid provides a comprehensive set of ready-to-use features that cover everything from paging, sorting, filtering, editing, and grouping to row virtualization, optimized data reading, keyboard navigation, and accessibility support. The Telerik Blazor grid is built on native Blazor from the ground up, by a company with a long history of making enterprise-ready Grids. This results in a highly customizable Grid that delivers lighting fast performance. @@ -151,6 +154,7 @@ The Grid supports custom content in various parts of the component such as data * [Drag and drop rows](slug:grid-drag-drop-overview)—move rows in a Grid or between different Grids. * [Loading animation](slug:grid-loading)—show a loading animation to improve user experience during long data operations. * Scrolling—the Grid will show standard scrollbars automatically if the data does not fit the current component width and height. +* [Highlighting](slug:grid-highlighting)—highlight rows or cells programmatically to draw attention to important data. ## Grid Parameters diff --git a/components/grid/selection/cells.md b/components/grid/selection/cells.md index d57d3fd55e..d90f54bdbe 100644 --- a/components/grid/selection/cells.md +++ b/components/grid/selection/cells.md @@ -237,3 +237,4 @@ When using [Grid templates](slug:components/grid/features/templates) with cell s * [Live Demo: Grid Cell Selection](https://demos.telerik.com/blazor-ui/grid/cell-selection) * [Blazor Grid](slug:grid-overview) +* [Grid Highlighting](slug:grid-highlighting) diff --git a/components/grid/selection/rows.md b/components/grid/selection/rows.md index 567060fce3..ed3fcef7a0 100644 --- a/components/grid/selection/rows.md +++ b/components/grid/selection/rows.md @@ -213,3 +213,4 @@ The Grid clears the `SelectedItems` collection when the user drags and drops sel * [Live Demo: Grid Row Selection](https://demos.telerik.com/blazor-ui/grid/row-selection) * [Blazor Grid](slug:grid-overview) +* [Grid Highlighting](slug:grid-highlighting) diff --git a/components/grid/state.md b/components/grid/state.md index 049bc989f1..fb6c7f7b6d 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/grid/templates/editor.md b/components/grid/templates/editor.md index 88c46218e8..d7e769dbf2 100644 --- a/components/grid/templates/editor.md +++ b/components/grid/templates/editor.md @@ -20,12 +20,13 @@ If you need more complex logic inside the editor template, compared to simple da >tip The Editor Template works in all edit modes (Inline, Popup, InCell). Before using it with InCell mode, review the [pertinent notes](slug:grid-editing-incell#editor-template). -When an input receives an `EditContext` (usually comes down as a cascading parameter), the framework also requires a `ValueExpression`. If you use two-way binding (the `@bind-Value` syntax), the `ValueExpression` is deducted from there. However, if you use only the `Value` property, you have to pass the `ValueExpression` yourself. This is a lambda expression that tells the framework what field in the model to update. The following sample demonstrates how to achieve that. You can also check the [Requires a value for ValueExpression](slug://common-kb-requires-valueexpression) knowledge base article for more details. +When an input receives an `EditContext` (usually as a cascading parameter), the framework also requires a `ValueExpression`. If you use two-way binding (the `@bind-Value` syntax), the `ValueExpression` is deducted from there. However, if you use only the `Value` parameter, you have to pass the `ValueExpression` explicitly. This is a lambda expression that tells the framework what property of the model to use for validation. The following sample demonstrates how to achieve that. You can also check the [Requires a value for ValueExpression](slug:common-kb-requires-valueexpression) knowledge base article for more details.
````RAZOR @@ -33,7 +34,6 @@ When an input receives an `EditContext` (usually comes down as a cascading param @* Applies to the other input type components as well *@ ```` - **In this article:** * [Notes](#notes) @@ -46,39 +46,30 @@ When an input receives an `EditContext` (usually comes down as a cascading param * @[template](/_contentTemplates/common/inputs.md#edit-debouncedelay) -* The Grid row creates an `EditContext` and passes it to the `EditorTemplate`. You can read more about it in the [**Notes** section of the Editing Overview](slug:grid-editing-overview#notes) article. - * We recommend casting the Editor Template context to your model and storing it in a local or a dedicated global variable. Do not share a global variable within multiple templates, like column (cell) template and editor template. Variable sharing can lead to unexpected behavior. -* Direct casting of the `context` can make the data binding not work properly. - - ->caption Not recommended: direct casting. Binding does not work properly. +* Direct casting of the `context` can make two-way data binding not work properly. -
+>caption Not recommended: direct casting with two-way parameter binding -````RAZOR +````RAZOR.skip-repl ```` ->caption Recommended: cast the context to your model type and store it in a variable. Binding works as expected. +>caption Recommended: cast the context in advance
````RAZOR @{ - EditedProduct = context as Product; + var editProduct = (Product)context; - + } - -@code{ - private Product EditedProduct { get; set; } -} ```` ## Examples diff --git a/components/multicolumncombobox/data-bind.md b/components/multicolumncombobox/data-bind.md index fa4826e313..2ccbc89eb6 100644 --- a/components/multicolumncombobox/data-bind.md +++ b/components/multicolumncombobox/data-bind.md @@ -53,7 +53,7 @@ Missing selection is most common when: ## Missing Value or Data -The MultiColumnCombobox component attempts to infer the type of its model and value based on the provided `Data` and initial `Value`. This affects its [object reference](slug:multicolumncombobox-overview#component-reference-and-methods). +The MultiColumnCombobox component attempts to infer the type of its model and value based on the provided `Data` and initial `Value`. This affects its [object reference](slug:common-features-data-binding-overview#component-type). In case you cannot provide either the `Value` or `Data` initially, you need to [set the corresponding types to the `TItem` and `TValue` parameters](slug:common-features-data-binding-overview#component-type). diff --git a/components/multicolumncombobox/overview.md b/components/multicolumncombobox/overview.md index 313e883c97..ea6b2b9cd8 100644 --- a/components/multicolumncombobox/overview.md +++ b/components/multicolumncombobox/overview.md @@ -166,11 +166,7 @@ The MultiColumnComboBox provides the following popup settings: ## Component Reference and Methods -To execute MultiColumnComboBox methods, obtain reference to the component instance via `@ref`. - -The MultiColumnComboBox is a generic component. Its type depends on the type of its model and the type of its `Value`. In case you cannot provide either the `Value` or `Data` initially, you need to [set the corresponding types to the `TItem` and `TValue` parameters](slug:common-features-data-binding-overview#component-type). - -The table below lists the MultiComboBox methods. Also consult the [MultiColumnComboBox API](slug:Telerik.Blazor.Components.TelerikMultiColumnComboBox-2). +Add a reference to the component instance to use the [MultiColumnComboBox's methods](slug:Telerik.Blazor.Components.TelerikMultiColumnComboBox-2). Note that the [MultiColumnComboBox is a generic component](slug:common-features-data-binding-overview#component-type). | Method | Description | | --- | --- | diff --git a/components/multiselect/data-bind.md b/components/multiselect/data-bind.md index 6000ec15c2..d21e142013 100644 --- a/components/multiselect/data-bind.md +++ b/components/multiselect/data-bind.md @@ -128,57 +128,7 @@ To bind the MultiSelect to a model: ## Considerations -The MultiSelect component attempts to infer the type of its model and value based on the provided `Data` and initial `Value`. This affects the way its [reference is obtained](#reference) and what happens [if you can't provide data or a value](#missing-value-or-data). - -### Reference - -The MultiSelect is a generic component and its type depends on the type of its `Data` and `Value`. - -
-````RAZOR String -@*Reference type when binding to a string collection*@ - - - -@code { - private TelerikMultiSelect? MultiSelectRef { get; set; } - - private List MultiSelectValue { get; set; } = new(); - - private List MultiSelectData { get; set; } = new List { "first", "second", "third" }; -} -```` -````RAZOR Model -@*Reference when binding to a model collection*@ - - - -@code { - private TelerikMultiSelect? MultiSelectRef { get; set; } - - private List MultiSelectValue { get; set; } = new(); - - private List MultiSelectData { get; set; } = new List() - { - new MultiSelectItem { Text = "first", Value = 1 }, - new MultiSelectItem { Text = "second", Value = 2 }, - new MultiSelectItem { Text = "third", Value = 3 } - }; - - public class MultiSelectItem - { - public string Text { get; set; } = string.Empty; - - public int Value { get; set; } - } -} -```` +The MultiSelect component attempts to infer the type of its model and value based on the provided `Data` and initial `Value`. This affects the way its [reference is obtained](slug:common-features-data-binding-overview#component-type) and what happens [if you can't provide data or a value](#missing-value-or-data). ### Missing Value Or Data diff --git a/components/multiselect/overview.md b/components/multiselect/overview.md index f95842f7f3..734da0ac2b 100644 --- a/components/multiselect/overview.md +++ b/components/multiselect/overview.md @@ -14,47 +14,63 @@ The Blaz ## Creating MultiSelect -1. Use the `TelerikMultiSelect` tag to add the component to your razor page. +1. Add the `TelerikMultiSelect` tag to your razor page. +1. [Bind the `Data` parameter to the collection of objects or strings](slug:multiselect-databind) that you want to appear in the dropdown. +1. Set the `TextField` parameter to point to the object property that holds the user-readable value. +1. Set the `ValueField` parameter to point to the object property that holds the data item value. +1. [Bind the `Value` of the component](slug:get-started-value-vs-data-binding#value-binding) to a collection of the same type as the type defined by the `ValueField` parameter. +1. (optional) Configure additional features like `AutoClose`, `Placeholder`, or `ShowClearButton`. -1. Populate the `Data` property with the collection of items that you want to appear in the dropdown. - -1. [Bind the value of the component](slug:get-started-value-vs-data-binding#value-binding) to a collection of the same type as the type defined in the `ValueField` parameter. - -1. (Optional) Enable features like placeholder text, clear button, and AutoClose. - ->caption MultiSelect two-way value binding, main features, and simple [data binding](slug:multiselect-databind) +>caption Basic Blazor MultiSelect two-way value binding, main features, and simple [data binding](slug:multiselect-databind) ````RAZOR -@* Main features and simple data binding for the suggestions and the Value *@ + @bind-Value="@MultiSelectValues" + TextField="@nameof(Country.Name)" + ValueField="@nameof(Country.Id)" + AutoClose="false" + Placeholder="Select Balkan Countries" + ShowClearButton="true"> -@if (Values.Count > 0) + +@if (MultiSelectValues.Count > 0) {
    - @foreach (var item in Values) + @foreach (int countryId in MultiSelectValues) { -
  • @item
  • +
  • Id @countryId, Name @Countries.First(x => x.Id == countryId).Name
  • }
} @code { - List Countries { get; set; } = new List(); - List Values { get; set; } = new List(); + private List Countries { get; set; } = new(); + private List MultiSelectValues { get; set; } = new(); + protected override void OnInitialized() { - Countries.Add("Albania"); - Countries.Add("Bosnia & Herzegovina"); - Countries.Add("Bulgaria"); - Countries.Add("Croatia"); - Countries.Add("Kosovo"); - Countries.Add("North Macedonia"); - Countries.Add("Montenegro"); - Countries.Add("Serbia"); - Countries.Add("Slovenia"); - base.OnInitialized(); + Countries.Add(new(1, "Albania")); + Countries.Add(new(2, "Bosnia and Herzegovina")); + Countries.Add(new(3, "Bulgaria")); + Countries.Add(new(4, "Croatia")); + Countries.Add(new(5, "Greece")); + Countries.Add(new(6, "Kosovo")); + Countries.Add(new(7, "Montenegro")); + Countries.Add(new(8, "Romania")); + Countries.Add(new(9, "Serbia")); + Countries.Add(new(10, "Slovenia")); + Countries.Add(new(11, "Turkey")); + } + + public class Country + { + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + + public Country(int id, string name) + { + Id = id; + Name = name; + } } } ```` @@ -165,9 +181,8 @@ The MultiSelect provides the following popup settings: ## MultiSelect Reference and Methods -The MultiSelect is a generic component and its type is determined by the type of the model you use as its data source. You can find examples in the [Data Bind - Considerations](slug:multiselect-databind#considerations) article. +Add a reference to the component instance to use the [MultiSelect's methods](slug:Telerik.Blazor.Components.TelerikMultiSelect-2). Note that the [MultiSelect is a generic component](slug:common-features-data-binding-overview#component-type). -Add a reference to the component instance to use the [MultiSelect's methods](slug:Telerik.Blazor.Components.TelerikMultiSelect-2). @[template](/_contentTemplates/dropdowns/methods.md#methods-list) diff --git a/components/panelbar/data-binding/overview.md b/components/panelbar/data-binding/overview.md index b3d735677a..9381161ec3 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 80a45dd9e4..accc52ec2e 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; } diff --git a/components/pdfviewer/form-filling.md b/components/pdfviewer/form-filling.md new file mode 100644 index 0000000000..4980b39526 --- /dev/null +++ b/components/pdfviewer/form-filling.md @@ -0,0 +1,33 @@ +--- +title: Form Filling +page_title: PDFViewer - Form Filling +meta_title: Form Filling | PDFViewer for Blazor +position: 17 +description: "Enable users to fill and submit PDF forms in the Blazor PDFViewer." +tags: telerik,blazor,pdfviewer,form filling,forms +slug: pdfviewer-form-filling +--- + +# Form Filling + +The PDFViewer enables users to fill interactive forms directly in PDF documents. You can display and edit form fields such as text boxes, checkboxes, radio buttons, and dropdowns. + +## Supported Form Fields + +The PDFViewer supports the following form field types: + +* `TextBox` +* `CheckBox` +* `RadioButton` +* `DropdownList` +* `ListBox` +* `Button` + +>caption Edit form fields and download the updated PDF file + + + +## See Also + +* [PDFViewer Overview](slug:pdfviewer-overview) +* [PDFViewer Events](slug:pdfviewer-events) diff --git a/components/pdfviewer/overview.md b/components/pdfviewer/overview.md index 1b62e3f6b3..86e2dc562d 100644 --- a/components/pdfviewer/overview.md +++ b/components/pdfviewer/overview.md @@ -63,6 +63,10 @@ The [PdfViewer toolbar can render built-in and custom tools](slug:pdfviewer-tool The PdfViewer provides a built-in option for creating and editing annotations. Explore the [available annotation types and how to work with them](slug:pdfviewer-annotations). +## Form Filling + +The PdfViewer supports interactive form filling in PDF documents. You can display and edit form fields such as text boxes, checkboxes, radio buttons, and dropdowns. For more details and examples, see the [Form Filling documentation](slug:pdfviewer-form-filling). + ## Large File Support In Blazor **Server** apps, the PDF Viewer uses the **SignalR WebSocket** to: @@ -81,6 +85,7 @@ The table below lists the PDF Viewer parameters. Also check the [PDF Viewer API | Parameter | Type and Default Value | Description | | --- | --- | --- | +| `AnnotationMode` | `PdfViewerAnnotationMode`
(`Disable`) | Specifies how the PDFViewer handles [form fields](slug:pdfviewer-form-filling) in the loaded document. | | `Class` | `string` | An additional CSS class for the `
` element. Use it to [customize the component styles and override the theme](slug:themes-override). | | `Data` | `byte[]` | The source of the currently displayed PDF file. | | `EnableLoaderContainer` | `bool`
(`true`) | Determines if the PDF Viewer will show a loading animation during opening, downloading or zooming a PDF file. | @@ -100,6 +105,7 @@ The PdfViewer exposes methods for programmatic operation. To use them, define a | --- | --- | | `Print` | Prints the loaded PDF document as an alternative to the [built-in Print button in the PDF Viewer toolbar](slug:pdfviewer-toolbar#built-in-tools). | | `Rebind` | Refreshes the PDF Viewer and ensures it is displaying the latest file `Data`. [`Rebind` is necessary when the Blazor framework cannot re-render components automatically](slug:common-features-data-binding-overview#refresh-data). | +| `GetFileAsync` | Asynchronously retrieves the current PDF file data as a byte array, including any annotations or form filling changes. Returns a `Task`. Returns `null` if no document is loaded. | >caption PDF Viewer reference and method usage diff --git a/components/scheduler/recurrence.md b/components/scheduler/recurrence.md index 520933e4e6..e1f09181fe 100644 --- a/components/scheduler/recurrence.md +++ b/components/scheduler/recurrence.md @@ -30,7 +30,7 @@ You can also [define custom property names](slug:scheduler-appointments-databind * `RecurrenceExceptionsField` * `RecurrenceIdField` -A single Scheduler data item defines one series of recurring appointments. Set the `RecurrenceRule` value, according to the [RFC5545 standard](https://tools.ietf.org/html/rfc5545#section-3.3.10). Then, if exceptions to the recurrence rule exist: +A single Scheduler data item defines one series of recurring appointments. Set the `RecurrenceRule` value, according to the [RFC5545 standard](https://tools.ietf.org/html/rfc5545#section-3.3.10), except for a [known discrepancy with extra hyphens in `UNTIL`](https://feedback.telerik.com/blazor/1529000-recurrencerule-does-not-support-the-rfc5545-date-format-like-20210722t000000). Then, if exceptions to the recurrence rule exist: * Each exception must be a separate data item. * The `RecurrenceId` property of each exception must be equal to `Id` value of the recurring appointment. @@ -213,7 +213,6 @@ A single Scheduler data item defines one series of recurring appointments. Set t public Appointment() { - var rand = new Random(); Id = Guid.NewGuid(); } } diff --git a/components/speechtotextbutton/appearance.md b/components/speechtotextbutton/appearance.md new file mode 100644 index 0000000000..d5b68ba16c --- /dev/null +++ b/components/speechtotextbutton/appearance.md @@ -0,0 +1,75 @@ +--- +title: Appearance +page_title: SpeechToTextButton Appearance +description: Customize the appearance of the SpeechToTextButton component in Blazor applications. +slug: speechtotextbutton-appearance +tags: blazor, speech recognition, appearance, customization +published: true +position: 2 +--- + +# SpeechToTextButton Appearance + +You can customize the appearance of the SpeechToTextButton component by using its built-in parameters and CSS classes. The component supports the same appearance options as the [Telerik UI for Blazor Button](slug:components/button/overview). + +## Size + +You can increase or decrease the size of the button by setting the `Size` parameter to a member of the `Telerik.Blazor.ThemeConstants.Button.Size` class. + +To review all available values for the `Size` parameter, see the [Button Size API Reference](https://docs.telerik.com/blazor-ui/api/Telerik.Blazor.ThemeConstants.Button.Size.html). + +>caption Example of setting the Button Size + + + +## Fill Mode + +The `FillMode` toggles the background and border of the TelerikSpeechToTextButton. You can set the parameter to a member of the `Telerik.Blazor.ThemeConstants.Button.FillMode` class. + +To review all available values for the `FillMode` parameter, see the [Button FillMode API Reference](https://docs.telerik.com/blazor-ui/api/Telerik.Blazor.ThemeConstants.Button.FillMode.html). + +>caption Example of setting the FillMode + + + +## Theme Color + +The color of the button is controlled through the `ThemeColor` parameter. You can set it to a member of the `Telerik.Blazor.ThemeConstants.Button.ThemeColor` class. + +To review all available values for the `ThemeColor` parameter, see the [Button ThemeColor API Reference](https://docs.telerik.com/blazor-ui/api/Telerik.Blazor.ThemeConstants.Button.ThemeColor.html). + +>caption Example of setting the ThemeColor + + + +## Rounded + +The `Rounded` parameter applies the border-radius CSS rule to the button to achieve curving of the edges. You can set it to a member of the `Telerik.Blazor.ThemeConstants.Button.Rounded` class. + +To review all available values for the `Rounded` parameter, see the [Button Rounded API Reference](https://docs.telerik.com/blazor-ui/api/Telerik.Blazor.ThemeConstants.Button.Rounded.html). + +>caption Example of Setting the Rounded parameter + + + +## Icon + +Set the `Icon` parameter to display an icon. You can use a predefined [Telerik icon](slug:common-features-icons) or a custom one. + +>caption Example of customizing the default icon + + + +## Custom Styles + +Use the `Class` parameter to apply custom CSS classes. You can further style the button by targeting these classes. + +>caption Example of custom styling + + + +## See Also + +- [SpeechToTextButton Overview](slug:speechtotextbutton-overview) +- [SpeechToTextButton Events](slug:speechtotextbutton-events) +- [SpeechToTextButton Integration](slug:speechtotextbutton-integration) \ No newline at end of file diff --git a/components/speechtotextbutton/events.md b/components/speechtotextbutton/events.md new file mode 100644 index 0000000000..3aaf680246 --- /dev/null +++ b/components/speechtotextbutton/events.md @@ -0,0 +1,45 @@ +--- +title: Events +page_title: SpeechToTextButton Events +description: Learn about the events that the SpeechToTextButton component emits and how to handle them in Blazor applications. +slug: speechtotextbutton-events +tags: blazor, speech recognition, events +published: true +position: 3 +--- + +# SpeechToTextButton Events + +The SpeechToTextButton component emits events that notify you about speech recognition results, errors, and state changes. Use these events to update the UI, display messages, or process the recognized speech. + +## OnResult + +The `OnResult` event fires when the component recognizes speech and produces a result. Use this event to access the recognized phrases, alternatives, and confidence scores. + +To review all available properties of the event arguments for `OnResult`, see the [`SpeechToTextButtonResultEventArgs` API Reference](https://docs.telerik.com/blazor-ui/api/Telerik.Blazor.Components.SpeechToTextButtonResultEventArgs.html). + +>caption Example: Displaying recognized Alternatives and Confidence + + + +## OnStart and OnEnd + +The `OnStart` event fires when speech recognition starts. The `OnEnd` event fires when speech recognition ends. Use these events to update the UI or track the recognition state. + +>caption Example: Indicating listening state + + + +## OnError + +The `OnError` event fires when an error occurs during speech recognition. Use this event to display error messages to the user. + +## OnClick + +The `OnClick` event fires when the user clicks or taps the button. It receives argument of type `MouseEventArgs`. + +## See Also + +- [SpeechToTextButton Overview](slug:speechtotextbutton-overview) +- [SpeechToTextButton Appearance](slug:speechtotextbutton-appearance) +- [SpeechToTextButton Integration](slug:speechtotextbutton-integration) \ No newline at end of file diff --git a/components/speechtotextbutton/integration.md b/components/speechtotextbutton/integration.md new file mode 100644 index 0000000000..a371f57679 --- /dev/null +++ b/components/speechtotextbutton/integration.md @@ -0,0 +1,28 @@ +--- +title: Integration +page_title: Integration +description: Learn how to integrate the SpeechToTextButton component with forms and other components in Blazor applications. +slug: speechtotextbutton-integration +tags: blazor, speech recognition, integration +published: true +position: 4 +--- + +# SpeechToTextButton Integration + +Integrate the SpeechToTextButton component with forms, input fields, and other UI elements to provide voice input capabilities. + +## Binding Recognized Text to an Input Field + +Use the `OnResult` event to update an input field with the recognized text. For example, you can enable users to fill out a feedback form by speaking instead of typing. When the user clicks the SpeechToTextButton, the component captures their speech. It then updates the value of a [TelerikTextArea](slug:textarea-overview) with the recognized text. + +>caption Example of binding the recognized text to an TelerikTextArea + + + +## See Also + +- [AI Model Voice Transcription Intergration](https://github.com/telerik/blazor-ui/tree/master/common/microsoft-extensions-ai-integration/SpeechToTextIntegration) +- [SpeechToTextButton Overview](slug:speechtotextbutton-overview) +- [SpeechToTextButton Events](slug:speechtotextbutton-events) +- [SpeechToTextButton Appearance](slug:speechtotextbutton-appearance) \ No newline at end of file diff --git a/components/speechtotextbutton/overview.md b/components/speechtotextbutton/overview.md new file mode 100644 index 0000000000..e07277703d --- /dev/null +++ b/components/speechtotextbutton/overview.md @@ -0,0 +1,70 @@ +--- +title: Overview +page_title: SpeechToTextButton Overview +description: Learn about the SpeechToTextButton component, its features, and how to use it in Blazor applications. +slug: speechtotextbutton-overview +tags: blazor, speech recognition, button, voice input +published: true +position: 1 +--- + +# Blazor SpeechToTextButton Overview + +The [Blazor SpeechToTextButton component](https://www.telerik.com/blazor-ui/speech-to-text-button) enables speech recognition in Blazor applications. It provides a button that users can select to start and stop speech recognition. The component converts spoken words into text and emits events with the recognized results. + +Use the SpeechToTextButton component to add voice input capabilities to forms, search bars, chat interfaces, and other scenarios that require speech-to-text functionality. + +## Basic Usage + +The following example demonstrates how to add the SpeechToTextButton to a Blazor page and handle the recognition result. + +>caption Example of using the SpeechToTextButton + + + +## Appearance + +You can customize the appearance of the SpeechToTextButton by setting parameters such as `Icon`, and `Class`. For more details and examples, refer to [SpeechToTextButton Appearance](slug:speechtotextbutton-appearance). + +## Events + +The SpeechToTextButton component emits several events that you can handle. For more details, refer to [SpeechToTextButton Events](slug:speechtotextbutton-events). + +## SpeechToTextButton Parameters + +To review all available parameters for the SpeechToTextButton component, see the [SpeechToTextButton API Reference](https://docs.telerik.com/blazor-ui/api/Telerik.Blazor.Components.TelerikSpeechToTextButton#parameters). + +## SpeechToTextButton Reference and Methods + +The SpeechToTextButton component exposes several public methods that you can call from your code. For a full list and details, see the [SpeechToTextButton API Reference](https://docs.telerik.com/blazor-ui/api/Telerik.Blazor.Components.TelerikSpeechToTextButton#methods). + +>caption Example of Calling a Method by Reference + +
+````RAZOR + + +@code { + private async Task StartRecognition() + { + await speechToTextButtonRef.StartAsync(); + } +} +```` + +## Supported Browsers + +The SpeechToTextButton component relies on the Web Speech API. For a list of supported browsers, refer to the [Web Speech API documentation](https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API#browser_compatibility). + +## Next Steps + +* [Handle SpeechToTextButton Events](slug:speechtotextbutton-events) +* [SpeechToTextButton Integration](slug:speechtotextbutton-integration) + +## See Also + +* [SpeechToTextButton Live Demo](https://demos.telerik.com/blazor-ui/speechtotextbutton/overview) +* [SpeechToTextButton API Reference](/blazor-ui/api/Telerik.Blazor.Components.TelerikSpeechToTextButton) +* [SpeechToTextButton Events](slug:speechtotextbutton-events) +* [SpeechToTextButton Appearance](slug:speechtotextbutton-appearance) +* [SpeechToTextButton Integration](slug:speechtotextbutton-integration) \ No newline at end of file diff --git a/components/splitter/panes.md b/components/splitter/panes.md index 7d9c002e9e..1a6e54241d 100644 --- a/components/splitter/panes.md +++ b/components/splitter/panes.md @@ -27,6 +27,7 @@ Each Splitter pane is configured individually and offers the following parameter | `Max` | `string` | The maximum size the pane can have in pixels or percentages. When it is reached, the user cannot expand its size further. | | `Min` | `string` | The minimum size the pane can have in pixels or percentages. When it is reached, the user cannot reduce its size further. | | `Resizable` | `bool`
(`true`) | Whether users can resize the pane with a resize handle (splitbar) or the keyboard. Pane resizing always affects two panes. To enable resizing for a specific pane, at least one adjacent pane must be resizable too. | +| `Scrollable` | `bool` | Whether the browser automatically shows scrollbars in panes which do not fit their current content. | | `Size` | `string` | The pane `width` CSS style in [horizontal Splitters](slug:splitter-orientation), or the pane `height` in [vertical Splitters](slug:splitter-orientation). Supports two-way binding. The `Size` must be between the `Min` and `Max` values. See [Pane Size](#pane-size) below for more details on pane dimensions and behavior. | | `Visible` | `bool` | Defines if the pane element and splitbar render or not. When toggled at runtime, the pane's index remains unchanged, unlike when adding a pane with a conditional statement, which appends it at the end. Compare with the `Collapsed` parameter. | @@ -46,7 +47,7 @@ Each Splitter pane is configured individually and offers the following parameter
Collapsible pane with initial size in percentage.
- +

Right Pane

Non-collapsible and scrollable pane with no size. It will take up the remaining space in the component.
@@ -66,10 +67,6 @@ Each Splitter pane is configured individually and offers the following parameter } ```` -## Pane Scrolling - -To make a Splitter pane scrollable without using additional HTML markup or custom CSS styles, set the pane `Class` parameter to `k-scrollable`. See the example above. - ## Pane Dimensions The dimensions of a Splitter pane depend on: diff --git a/components/tabstrip/events.md b/components/tabstrip/events.md index 2753e31fde..4a2ee8522c 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 was added in [version 9.0.0](https://www.telerik.com/support/whats-new/blazor-ui/release-history/telerik-ui-for-blazor-9-0-0-(2025-q2)). It 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 77d740a82a..a69aaf9b61 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 { @@ -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/components/timepicker/events.md b/components/timepicker/events.md index d56375a7fd..4e6af41cf1 100644 --- a/components/timepicker/events.md +++ b/components/timepicker/events.md @@ -22,49 +22,30 @@ This article explains the events available in the Telerik TimePicker for Blazor: The `ValueChanged` event fires upon every change (for example, keystroke) in the input, and upon clicking the `Set` or `Now` buttons in the dropdown. ->caption Handle ValueChanged +The event handler receives the new value as an argument and you must update the component `Value` programmatically for the user changes to take effect. -````RAZOR -@result -
- - - -@code { - string result; - - private void MyValueChangeHandler(DateTime theUserInput) - { - result = string.Format("The user entered: {0}", theUserInput); - } -} -```` - -@[template](/_contentTemplates/common/general-info.md#event-callback-can-be-async) - -@[template](/_contentTemplates/common/issues-and-warnings.md#valuechanged-lambda-required) - ->caption Handle ValueChanged and provide initial value +>caption Handle the TimePicker ValueChanged event ````RAZOR -@result +@Result
-model value: @thePickerValue +TimePicker Value: @TimePickerValue
- + + @code { - string result; + private string Result { get; set; } = string.Empty; - DateTime thePickerValue { get; set; } = DateTime.Now; + private DateTime TimePickerValue { get; set; } = DateTime.Now; - private void MyValueChangeHandler(DateTime theUserInput) + private void TimePickerValueChanged(DateTime newValue) { - result = $"The user entered: {theUserInput}"; + Result = $"The user entered: {newValue}"; - //you have to update the model manually because handling the ValueChanged event does not let you use @bind-Value - thePickerValue = theUserInput; + TimePickerValue = newValue; } } ```` @@ -75,22 +56,27 @@ The `OnChange` event represents a user action - confirmation of the current valu The time picker is a generic component, so you must provide either a `Value`, or a type to the `T` parameter of the component. ->caption Handle OnChange +>caption Handle the TimePicker OnChange event ````RAZOR -@result +@Result +
+TimePicker Value: @TimePickerValue
- + + @code { - string result; + private string Result { get; set; } = string.Empty; + + private DateTime TimePickerValue { get; set; } = DateTime.Now; - private void MyOnChangeHandler(object theUserInput) + private void OnTimePickerChange(object currentValue) { - // the handler receives an object that you may need to cast to the type of the component - // if you do not provide a Value, you must provide the Type parameter to the component - result = string.Format("The user entered: {0:HH:mm:ss}", (DateTime)theUserInput); + // Cast the event argument to the actual value type + Result = $"The user entered: {(DateTime)currentValue}"; } } ```` @@ -99,30 +85,6 @@ The time picker is a generic component, so you must provide either a `Value`, or >tip The `OnChange` event is a custom event and does not interfere with bindings, so you can use it together with models and forms. ->caption Handle OnChange and use two-way binding - -````RAZOR -@result -
-model value: @thePickerValue -
- - - -@code { - string result; - - DateTime? thePickerValue { get; set; } = DateTime.Now; - - private void MyOnChangeHandler(object theUserInput) - { - // the handler receives an object that you may need to cast to the type of the component - // if you do not provide a Value, you must provide the Type parameter to the component - result = string.Format("The user entered: {0}", (theUserInput as DateTime?).Value); - } -} -```` - ## OnOpen The `OnOpen` event fires before the TimePicker popup renders. diff --git a/components/timepicker/overview.md b/components/timepicker/overview.md index 9c19148452..d2d0bc8dec 100644 --- a/components/timepicker/overview.md +++ b/components/timepicker/overview.md @@ -88,6 +88,7 @@ The Blazor Time Picker component provides various parameters that allow you to c | `ReadOnly` | `bool` | If set to `true`, the component will be readonly and will not allow user input. The component is not readonly by default and allows user input. | | `Format` | `string`
(`ShortTimePattern`) | The format of the TimePicker's DateInput. The default value depends on `CultureInfo.CurrentCulture`. Read more at [Supported date formats by the DateInput](slug:components/dateinput/supported-formats). Note that format specifiers for non-time portions will be editable only in the input and will not have a representation in the Time Picker dropdown. | | `Id` | `string` | Renders as the `id` attribute on the `` element, so you can attach a `