diff --git a/_contentTemplates/dropdownbutton/notes.md b/_contentTemplates/dropdownbutton/notes.md index 368d02581c..5f8c5becb4 100644 --- a/_contentTemplates/dropdownbutton/notes.md +++ b/_contentTemplates/dropdownbutton/notes.md @@ -1,7 +1,7 @@ #dropdownbutton-splitbutton-comparison The DropDownButton and SplitButton components are similar. They both consist of a primary button and a dropdown element that holds additional action items. The major difference is the purpose of the primary button. -* [DropDownButton]({%slug dropdownbutton-overview%}) - The main purpose of the primary button is to open the popup with additional actions. The primary button does expose a separate [`OnClick` event]({%slug dropdownbutton-events%}), so you can handle it to invoke a dedicated action but clicking on it always opens the dropdown. +* [DropDownButton]({%slug dropdownbutton-overview%})—The main purpose of the primary button is to open the popup with additional actions. The primary button exposes a separate [`OnClick` event]({%slug dropdownbutton-events%}), which can invoke a dedicated action. Clicking on the DropDownButton always opens the dropdown. -* [SplitButton]({%slug splitbutton-overview%}) - The main element contains a primary button and a separate button for opening the dropdown. The purpose of the primary button is to [invoke a standalone action]({%slug splitbutton-events%}#onclick). Clicking on it does not open the dropdown. To open the popup with the additional actions, the user has to click the dedicated button with `caret-alt-down` icon. +* [SplitButton]({%slug splitbutton-overview%})—The main element contains a primary button and a separate button for opening the dropdown. The purpose of the primary button is to [invoke a standalone action]({%slug splitbutton-events%}#onclick). Clicking on it does not open the dropdown. To open the popup with the additional actions, the user has to click the dedicated button with `caret-alt-down` icon. It is possible to [switch the primary and dropdown actions programmatically]({%slug splitbutton-kb-change-primary-action-onclick%}). #end \ No newline at end of file diff --git a/components/grid/columns/resize.md b/components/grid/columns/resize.md index 7971ba88a6..56d0fa363f 100644 --- a/components/grid/columns/resize.md +++ b/components/grid/columns/resize.md @@ -66,8 +66,7 @@ The known limitations of the Autofit Columns feature include: >caption Grid Column Resizing and Autofitting ````CSHTML -@* Grid column resizing and autofitting *@ -@* Drag the border between column headers to change the column width. The command column is not resizable by the user. *@ +

Resize the Grid columns and click the AutoFit buttons. The command column is not resizable by the user.

AutoFit ID Column AutoFit String Columns @@ -76,38 +75,43 @@ The known limitations of the Autofit Columns feature include: + Pageable="true" + Sortable="true" + Height="300px"> - - - + + + - Update - Edit - Delete - Cancel + Edit + Delete @code { - public TelerikGrid GridRef { get; set; } - public List GridData { get; set; } + public TelerikGrid? GridRef { get; set; } + public List GridData { get; set; } = new(); + + // Columns IDs used in the Grid column definitions and in the AutoFit methods. + private const string IdColumnId = "id-column"; + private const string FirstNameColumnId = "first-name-column"; + private const string LastNameColumnId = "last-name-column"; private async Task AutoFitSingleColumn() { - await GridRef.AutoFitColumnAsync("IDColumn"); + await GridRef!.AutoFitColumnAsync(IdColumnId); } private async Task AutoFitMultipleColumns() { - var columns = new List() { "NameColumn1", "NameColumn2" }; - await GridRef.AutoFitColumnsAsync(columns); + var columnIds = new List() { FirstNameColumnId, LastNameColumnId }; + await GridRef!.AutoFitColumnsAsync(columnIds); } private async Task AutoFitAllColumns() { - await GridRef.AutoFitAllColumnsAsync(); + await GridRef!.AutoFitAllColumnsAsync(); } protected override void OnInitialized() @@ -120,7 +124,7 @@ The known limitations of the Autofit Columns feature include: return Enumerable.Range(1, 50).Select(x => new SampleData { Id = x, - Name = $"name {x}", + FirstName = $"Name {x}", LastName = $"Surname {x}" }).ToList(); } @@ -128,8 +132,8 @@ The known limitations of the Autofit Columns feature include: public class SampleData { public int Id { get; set; } - public string Name { get; set; } - public string LastName { get; set; } + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; } } ```` diff --git a/components/menu/images/menu-template-distinguish-item.png b/components/menu/images/menu-template-distinguish-item.png deleted file mode 100644 index 6fcc8455e2..0000000000 Binary files a/components/menu/images/menu-template-distinguish-item.png and /dev/null differ diff --git a/components/menu/templates.md b/components/menu/templates.md index 51c8cd93a8..0de113ea03 100644 --- a/components/menu/templates.md +++ b/components/menu/templates.md @@ -10,48 +10,66 @@ position: 10 # Menu Templates -The Menu component allows you to define a custom template for its items. This article explains how you can use it. +The Menu component allows you to define a custom template for its items. This article explains how to use it. -The `ItemTemplate` of an item is defined under the `ItemTemplate` tag of the menu. +## ItemTemplate -The template receives the model to which the item is bound as its `context`. You can use it to render the desired content. The menu is a generic component, so you can use a named context variable that will be of the model type without additional casting. +The template of all items is defined in the `ItemTemplate` tag of the Menu. -You can use the template to render arbitrary content according to your application's data and logic. You can use components in it and thus provide rich content instead of plain text. You can also use it to add DOM event handlers like click, doubleclick, mouseover if you need to respond to them. +The template receives the respective Menu data item as its `context`. You can use it to render the desired content. You can also set the `Context` parameter of the `ItemTemplate` tag and use a [named context variable. This is useful in nested template scenarios]({%slug nest-renderfragment%}). ->caption Use templates to implement navigation between views without the UrlField feature +The Menu item template can contain arbitrary content according such as HTML markup and other components. You can also use standard event handlers like `@onclick` or `@onmouseover`. + +## Examples + +### Use ItemTemplate for Navigation + +The following example shows how to render `` tags inside the Menu and use them for navigation instead of the [built-in Menu navigation mechanism]({%slug menu-navigation%}). This approach requires the URL property name to be different from `Url`. [`` also supports the `target="_blank"` attribute](#use-itemtemplate-for-styling-and-target_blank). + +>caption Use Menu item template for navigation ````CSHTML -Use your own NavLink elements for navigation instead of the built-in feature of the menu +

Menu with ItemTemplate

- + @{ - var shouldNavigate = !string.IsNullOrEmpty(item.Page); + @* + k-menu-link-text will make the NavLink similar to built-in Menu items. + You also need to reset the underline and text color. + Do not render an SvgIcon component if item.Icon is null. + *@ + + var shouldNavigate = !string.IsNullOrEmpty(item.Href); + if (shouldNavigate) { - @*k-menu-link-text will expand the NavLink to match default Menu styling*@ - @item.Section + + @item.Text } else { - @*k-menu-link-text will expand the span to match default Menu styling*@ - - See more about our @item.Section.ToLowerInvariant() + + @item.Text } } -@code { - public List MenuItems { get; set; } - - public class MenuItem - { - public string Section { get; set; } - public string Page { get; set; } - public List SubSectionList { get; set; } + + +

Default Menu

+ + + +@code { + public List MenuItems { get; set; } = new(); protected override void OnInitialized() { @@ -59,40 +77,62 @@ Use your own NavLink elements for navigation instead of the built-in feature of { new MenuItem() { - Section = "Company", - SubSectionList = new List() + Text = "Company", + Icon = SvgIcon.Globe, + Items = new List() { new MenuItem() { - Section = "Overview", - Page = "company/overview" + Text = "Overview", + Href = "company/overview", + Icon = SvgIcon.InfoCircle }, new MenuItem() { - Section = "Events", - Page = "company/events" + Text = "Events", + Href = "company/events", + Icon = SvgIcon.Calendar, + Items = new List() + { + new MenuItem() + { + Text = "Boston", + Href = "company/events/boston", + Icon = SvgIcon.Calendar + }, + new MenuItem() + { + Text = "Sofia", + Href = "company/events/sofia", + Icon = SvgIcon.Calendar + } + } }, new MenuItem() { - Section = "Careers", - Page = "company/careers" + Text = "Careers", + Href = "company/careers", + Icon = SvgIcon.User } } }, new MenuItem() { - Section = "Services", - SubSectionList = new List() + Text = "Services", + Icon = SvgIcon.Sparkles, + Items = new List() { new MenuItem() { - Section = "Consulting", - Page = "consultingservices" + Text = "Consulting", + Href = "consulting", + Icon = SvgIcon.Graph }, new MenuItem() { - Section = "Education", - Page = "education" + Text = "Education", + Href = "education", + Icon = SvgIcon.Book } } } @@ -100,40 +140,90 @@ Use your own NavLink elements for navigation instead of the built-in feature of base.OnInitialized(); } + + public class MenuItem + { + public string Text { get; set; } = string.Empty; + public string Href { get; set; } = string.Empty; + public ISvgIcon? Icon { get; set; } + public List? Items { get; set; } + } } ```` ->caption Use templates to visually distinguish the current page as an item that is styled differently, and to open external links in new tabs +### Use ItemTemplate for Styling and target="_blank" + +The example below shows a Menu configuration that is suitable for use in `MainLayout.razor`. The implementation disables the [built-in Menu navigation]({%slug menu-navigation%}) because the URL property is not `Url` and `UrlField` is not set. The sample also uses `` tags with `target="_blank"` to open external links in a new browser window. + +>caption Use Menu item template to distinguish the current page and open external links in new browser windows + +
````CSHTML -@inject NavigationManager navigationManager +@inject NavigationManager NavManager @{ + @* + k-menu-link-text will make the NavLink or span similar to built-in Menu items. + You also need to reset the underline and text color. + Do not render an SvgIcon component if item.Icon is null. + *@ + if (EqualityComparer.Default.Equals(item, SelectedMenuItem)) { - @*k-menu-link-text will expand the span to match default Menu styling*@ - @item.Text + + @item.Text } else { - string target = ""; - if (!IsInternalPage(item.Url)) + string target = string.Empty; + if (!IsInternalPage(item.Href)) { target = "_blank"; } - @*k-menu-link-text will expand the NavLink to match default Menu styling*@ - @item.Text + + @item.Text } } + + @code { - public List MenuItems { get; set; } + private List MenuItems { get; set; } = new(); + + private MenuItem? SelectedMenuItem { get; set; } + + private void OnClick(MenuItem item) + { + if (IsInternalPage(item.Href)) + { + SelectedMenuItem = item; + } + } - public MenuItem SelectedMenuItem { get; set; } + private bool CompareCurrentPageUrl(string urlToCompare) + { + return NavManager.Uri.Substring(NavManager.BaseUri.Length - 1).Equals(urlToCompare); + } + + private bool IsInternalPage(string url) + { + if (string.IsNullOrEmpty(url)) + { + return false; + } + return !(url.StartsWith("https://") || url.StartsWith("http://")); + } protected override void OnInitialized() { @@ -142,77 +232,59 @@ Use your own NavLink elements for navigation instead of the built-in feature of new MenuItem() { Text = "Home", - Url = "/", + Href = "/", + Icon = SvgIcon.Home }, new MenuItem() { - Text = "Fetch Data", - Url = "/fetchdata" + Text = "Counter", + Href = "/counter", + Icon = SvgIcon.Calculator }, new MenuItem() { - Text = "Counter", - Url = "/counter" + Text = "Weather", + Href = "/weather", + Icon = SvgIcon.Globe }, new MenuItem() { - Text = "Telerik UI for Blazor", + Text = "Telerik", + Href = "https://www.telerik.com", + Icon = SvgIcon.Star, Items = new List() { new MenuItem() { Text = "Documentation", - Url = "https://docs.telerik.com/blazor-ui/introduction" + Href = "https://docs.telerik.com/blazor-ui/introduction", + Icon = SvgIcon.Star }, new MenuItem() { - Text = "Live Demos", - Url = "https://demos.telerik.com/blazor-ui" + Text = "Demos", + Href = "https://demos.telerik.com/blazor-ui", + Icon = SvgIcon.Star } } } }; - SelectedMenuItem = MenuItems.Find(item => CompareCurrentPageUrl(item.Url)); + SelectedMenuItem = MenuItems.Find(item => CompareCurrentPageUrl(item.Href)); base.OnInitialized(); } - private void OnClick(MenuItem item) - { - if (IsInternalPage(item.Url)) - { - SelectedMenuItem = item; - } - } - - private bool CompareCurrentPageUrl(string urlToCopmare) - { - return navigationManager.Uri.Substring(navigationManager.BaseUri.Length - 1).Equals(urlToCopmare); - } - - private bool IsInternalPage(string url) - { - if (string.IsNullOrEmpty(url)) - { - return false; - } - return !(url.StartsWith("https://") || url.StartsWith("http://")); - } - public class MenuItem { - public string Text { get; set; } - public string Url { get; set; } - public List Items { get; set; } + public string Text { get; set; } = string.Empty; + public string Href { get; set; } = string.Empty; + public ISvgIcon? Icon { get; set; } + public List? Items { get; set; } } } ```` ->caption The result from the snippet above, assuming the current page URL is `/counter` - -![Blazor Menu Template Distinguish Item](images/menu-template-distinguish-item.png) - ## See Also * [Data Binding a Menu]({%slug components/menu/data-binding/overview%}) diff --git a/knowledge-base/splitbutton-dynamic-primary-change-onclick.md b/knowledge-base/splitbutton-dynamic-primary-change-onclick.md index 85e97b1004..55a4689349 100644 --- a/knowledge-base/splitbutton-dynamic-primary-change-onclick.md +++ b/knowledge-base/splitbutton-dynamic-primary-change-onclick.md @@ -44,15 +44,17 @@ This KB article answers the following questions: ````CSHTML @* Change SplitButton primary action on click *@ +

Last click action: @SplitButtonLog

+ @PrimaryButton.Text @{ - var secondaryButtons = AllSplitButtons.Where(x => x.Id != PrimaryButton.Id); - foreach (var button in secondaryButtons) + foreach (var button in SecondaryButtons) { - @button.Text @@ -61,8 +63,6 @@ This KB article answers the following questions: -Last click action: @SplitButtonLog - @code { private List AllSplitButtons { get; set; } = new List() { new SplitButtonModel() { Id = 1, Text = "Paste", Icon = SvgIcon.Clipboard }, @@ -70,6 +70,8 @@ Last click action: @SplitButtonLog new SplitButtonModel() { Id = 3, Text = "Paste as HTML", Icon = SvgIcon.ClipboardHtml }, }; + private List SecondaryButtons => AllSplitButtons.Where(x => x.Id != PrimaryButton.Id).ToList(); + private SplitButtonModel PrimaryButton { get; set; } = null!; private string SplitButtonLog { get; set; } = string.Empty;