Back to Devexpress

TagBox - Templates

blazor-405479-components-data-editors-tagbox-templates.md

latest18.9 KB
Original Source

TagBox - Templates

  • Jan 22, 2026
  • 9 minutes to read

TagBox templates are RenderFragment<TValue> type properties. These render fragments can contain both markup and other Razor components. A template’s Razor markup can access an implicit parameter named context. This parameter is derived from the TValue type and contains template-related members.

You can use the Context attribute to change the parameter name. This name change is essential when you nest components that contain RenderFragment<TValue> properties; otherwise, the following error can occur: The child content element ‘ChildContent’ of component ‘X’ uses the same parameter name (‘context’) ….

Item Display Template

Use the ItemDisplayTemplate property to customize the appearance of TagBox items. The property accepts a TagBoxItemDisplayTemplateContext<TData> object as the context parameter. You can use the parameter’s members to obtain item information:

The following code snippet uses the ItemDisplayTemplate property to display TagBox items in a card-like view. Each item shows an employee’s first name, last name, photo, and phone number.

razor
@inject NwindDataService NwindDataService

<DxTagBox Data="@Data"
          @bind-Values="@Values">
    <TagDisplayTemplate Context="tagContext">
        <div class="tagbox-tag-template">
            
            <div>@tagContext.DataItem.FullName</div>
            <DxButton Click="@tagContext.RemoveTagAction"
                        @onclick:stopPropagation
                        aria-label="Remove Tag"
                        CssClass="tagbox-tag-template-close-btn"
                        IconCssClass="tagbox-tag-template-close-btn-icon"
                RenderStyle="ButtonRenderStyle.None" RenderStyleMode="ButtonRenderStyleMode.Text">
            </DxButton>
        </div>
    </TagDisplayTemplate>
    <ItemDisplayTemplate>
        <div class="tagbox-item-template">
            
            <div>
                <span class="tagbox-item-template-employee-first-name">@context.DataItem.FullName</span>
                <span class="tagbox-item-template-employee-home-phone">@context.DataItem.HomePhone</span>
            </div>
        </div>
    </ItemDisplayTemplate>
</DxTagBox>

@code {
    IEnumerable<Employee> Data { get; set; }
    IEnumerable<Employee> Values { get; set; }
    protected override async Task OnInitializedAsync() {
        Data = await NwindDataService.GetEmployeesAsync();
        Values = Data.Take(1);
    }
    string GetImageFileName(Employee employee) {
        return $"employees/item-template{employee.EmployeeId}.jpg";
    }
}
css
.tagbox-item-template {
    display: flex;
    align-items: center;
}
.tagbox-tag-template {
    display: flex;
    align-items: center;
    padding: 0.125em 0.5em 0.125em 0;
    position: relative;
}
.tagbox-tag-template:before {
    content: " ";
    position: absolute;
    background-color: currentColor;
    opacity: 0.15;
    border-radius: 16px;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    pointer-events: none;
}
.tagbox-item-template-employee-photo,
.tagbox-tag-template-employee-photo {
    margin-right: 0.5em;
    border-radius: 16px;
    border: 0 solid #000;
}
.tagbox-item-template-employee-photo {
    border-radius: 50%;
    width: 2rem;
    height: 2rem;
}
.tagbox-tag-template-employee-photo {
    width: 24px;
    height: 24px;
}
.tagbox-item-template-employee-home-phone {
    opacity: 0.65;
    display: block;
}
.tagbox-tag-template-close-btn {
    border: 0;
    border-radius: 3rem;
    box-shadow: none;
    font-weight: 600;
    padding: 0;
    width: 16px;
    height: 16px;
    margin: 0 0 0 0.5em;
    opacity: 0.5;
}
.tagbox-tag-template-close-btn:hover {
    opacity: 0.75;
}
.tagbox-tag-template-close-btn-icon {
    height: 16px;
    width: 16px;
    mask-image: url("images/icons/clear.svg");
    -webkit-mask-image: url("images/icons/clear.svg");
    background-size: contain;
    mask-repeat: no-repeat;
    -webkit-mask-repeat: no-repeat;
    background-position: center center;
    background-color: currentColor;
}
css
public partial class Employee {
    public Employee() {
        this.Orders = new List<Order>();
    }
    public int EmployeeId { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Title { get; set; }
    public string TitleOfCourtesy { get; set; }
    public Nullable BirthDate { get; set; }
    public Nullable HireDate { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string Region { get; set; }
    public string PostalCode { get; set; }
    public string Country { get; set; }
    public string HomePhone { get; set; }
    public string Extension { get; set; }
    public byte[] Photo { get; set; }
    public string Notes { get; set; }
    public Nullable<int> ReportsTo { get; set; }
    public string PhotoPath { get; set; }
    public string GroupName { get; set; }
    public virtual ICollection<Order> Orders { get; set; }
    public string Text => $"{FirstName} {LastName} ({Title})";
    public string FullName => $"{FirstName} {LastName}";
    public string ImageFileName => $"employees/{EmployeeId}.jpg";
}
csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BlazorDemo.Data.Northwind;
using BlazorDemo.DataProviders;

namespace BlazorDemo.Services {
    public partial class NwindDataService {
        public Task<IEnumerable<Employee>> GetEmployeesAsync(CancellationToken ct = default) {
            // Return your data here
        }
    }
}
csharp
public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        // ...
        services.AddScoped<NwindDataService>();
    }
}

Run Demo: TagBox - ItemTemplate

Tag Display Template

Use the TagDisplayTemplate property to customize tag appearance. The property accepts a TagBoxTagDisplayTemplateContext<TData> object as the context parameter. You can use the parameter’s members to obtain tag information:

The following code snippet customizes a tag appearance according to its type and text.

razor
<DxTagBox Data="@Data"
                  TextFieldName="@nameof(City.CityName)"
                  TData="City"
                  TValue="City"
                  AllowCustomTags="true"
                  @bind-Tags="@Tags"
                  ListRenderMode="ListRenderMode.Virtual"
                  SizeMode="Params.SizeMode"
                  CssClass="cw-480"
                  InputId="tbTagTemplate">
            <TagDisplayTemplate Context="tagContext">
                @{
                    var buttonStyleMode = tagContext.IsCustom ? ButtonRenderStyleMode.Contained : GetModeByID(tagContext.DataItem.CityName);
                    var buttonStyle = tagContext.IsCustom ? ButtonRenderStyle.Dark : ButtonRenderStyle.Primary;
                    <DxButton tabindex="-1"
                              RenderStyle="@buttonStyle"
                              RenderStyleMode="@buttonStyleMode"
                              Text="@tagContext.DisplayText"
                              CssClass="tagbox-tag-template-btn">

                        @context
                        <span @onclick="@tagContext.RemoveTagAction" class="tagbox-tag-template-close-btn-icon">&times;</span>
                    </DxButton>
                }
            </TagDisplayTemplate>
        </DxTagBox>
@* ... *@

@code {
    IEnumerable<City> Data { get; set; }
    IEnumerable<string> Tags { get; set; }

    protected override async Task OnInitializedAsync() {
        Data = await WorldcitiesDataService.GetCitiesAsync();
        Tags = new List<string>() { "New York", "Los Angeles", "Tokyo" };
    }

    ButtonRenderStyleMode GetModeByID(string cityName) {
        switch(cityName) {
            case "New York":
                return ButtonRenderStyleMode.Contained;
            case "Los Angeles":
                return ButtonRenderStyleMode.Outline;
            default:
                return ButtonRenderStyleMode.Text;
        }
    }
}
csharp
public class City {
    public int Id { get; set; }
    public int CountryId { get; set; }
    public string CityName { get; set; }
}

public static class CityData {
    private static readonly Lazy<List<City>> cities = new Lazy<List<City>>(() => {
        return new List<City>() {
            new City() { Id = 0, CountryId = 0, CityName = "Washington" },
            new City() { Id = 1, CountryId = 0, CityName = "New York" },
            new City() { Id = 2, CountryId = 0, CityName = "Los Angeles" },
            new City() { Id = 3, CountryId = 1, CityName = "Berlin" },
            new City() { Id = 4, CountryId = 1, CityName = "Munich" },
            new City() { Id = 5, CountryId = 1, CityName = "Hamburg" },
            new City() { Id = 6, CountryId = 2, CityName = "Tokyo" },
            new City() { Id = 7, CountryId = 2, CityName = "Osaka" },
            new City() { Id = 8, CountryId = 2, CityName = "Yokohama" }
        };
    });
    public static List<City> Cities { get { return cities.Value; } }
}
csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BlazorDemo.Data.Worldcities;
using BlazorDemo.DataProviders;

namespace BlazorDemo.Services {
    public partial class WorldcitiesDataService {
        public Task<IEnumerable<City>> GetCitiesAsync(CancellationToken ct = default) {
            // Return your data here
        }
    }
}
csharp
publicclassStartup {
    publicvoidConfigureServices(IServiceCollection services) {
        // ...
        services.AddScoped<WorldcitiesDataService>();
    }
}

Run Demo: TagBox - Tag Display Template

Cell Display Templates

Use the following properties to customize cell appearance in a multi-column TagBox.

PropertyContainerScope
ColumnCellDisplayTemplateDxTagBoxAll cells in a TagBox
CellDisplayTemplateDxListEditorColumnCells in the current column

These properties can be combined within a single TagBox. If both templates are defined, the column-specific CellDisplayTemplate takes precedence over the global ColumnCellDisplayTemplate for cells in that particular column. This functionality allows you to set a common template for all columns and then override it for individual columns that require different formatting.

The following code snippet customizes the appearance of different columns in a TagBox control:

razor
<DxTagBox Data="Subscriptions.Plans"
            @bind-Values="SelectedPlans"
            EditFormat="{0}">
    <Columns>
        <DxListEditorColumn FieldName="Name" Caption="Plan">
            <CellDisplayTemplate>
                <div class="text-left">
                    <b>@context.Value Subscription</b>
                </div>
            </CellDisplayTemplate>
        </DxListEditorColumn>
        <DxListEditorColumn FieldName="PriceMonth" Caption="Month" />
        <DxListEditorColumn FieldName="PriceQuarter" Caption="Quarter" />
        <DxListEditorColumn FieldName="PriceYear" Caption="Year" />
    </Columns>
    <ColumnCellDisplayTemplate>
        <div class="text-right">
            @($"{context.Value:C}")
        </div>
    </ColumnCellDisplayTemplate>
</DxTagBox>

@code {
    IEnumerable<SubscriptionPlan> SelectedPlans { get; set; }
}
csharp
public class SubscriptionPlan(
    int id,
    string name,
    int priceMonth,
    int priceQuarter,
    int priceYear
    )
{
    public int Id { get; set; } = id;
    public string Name { get; set; } = name;
    public int PriceMonth { get; set; } = priceMonth;
    public int PriceQuarter { get; set; } = priceQuarter;
    public int PriceYear { get; set; } = priceYear;
}
csharp
public static class Subscriptions
{
    public static List<SubscriptionPlan> Plans { get; } = [
        new SubscriptionPlan(1, "Basic", 10, 25, 90),
        new SubscriptionPlan(2, "Standard", 20, 50, 180),
        new SubscriptionPlan(3, "Premium", 30, 75, 270),
        new SubscriptionPlan(4, "Enterprise", 50, 125, 450)
        ];
}
css
.text-right {
    text-align: right;
}
.text-left {
    text-align: left;
}

Run Demo: TagBox - Cell Display Template

Empty Data Area Template

The TagBox displays an empty data area in the following cases:

  • The Data property is unset.
  • The specified data source is empty.
  • None of the TagBox items matches the current search and filter condition.
  • You use the DataAsync property or the CustomData property to bind the TagBox to a data source. The component sends the first request to a remote data source and waits for a response.

Use the EmptyDataAreaTemplate to customize the content displayed in this empty region. The template’s context parameter includes the IsDataLoading property that allows you to determine whether the TagBox is loading data.

razor
@inject NwindDataService NwindDataService

<DxTagBox Data="@DataItems"
          @bind-Values="@Items"
          CssClass="cw-480"
          NullText="Select an order..."
         >
    <EmptyDataAreaTemplate>
        @if (!context.IsDataLoading) {
            <div class="empty-data-area-template">
                <div class="d-flex flex-column">
                    No orders found
                </div>
            </div>
        }
    </EmptyDataAreaTemplate>
</DxTagBox>

@code {
    IEnumerable<string> DataItems { get; set; }
    IEnumerable<string> Items { get; set; }
}
css
.empty-data-area-template {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 150px;
    padding: 2rem 0;
}
csharp
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

public partial class Employee {
    public Employee() {
        this.Orders = new List<Order>();
    }
    public int EmployeeId { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Title { get; set; }
    public string TitleOfCourtesy { get; set; }
    public Nullable BirthDate { get; set; }
    public Nullable HireDate { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string Region { get; set; }
    public string PostalCode { get; set; }
    public string Country { get; set; }
    public string HomePhone { get; set; }
    public string Extension { get; set; }
    public byte[] Photo { get; set; }
    public string Notes { get; set; }
    public Nullable<int> ReportsTo { get; set; }
    public string PhotoPath { get; set; }
    public string GroupName { get; set; }
    public virtual ICollection<Order> Orders { get; set; }
    public string Text => $"{FirstName} {LastName} ({Title})";
    public string FullName => $"{FirstName} {LastName}";
    public string ImageFileName => $"employees/{EmployeeId}.jpg";
}
csharp
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BlazorDemo.Data.Northwind;
using BlazorDemo.DataProviders;

namespace BlazorDemo.Services {
    public partial class NwindDataService {
        public Task<IEnumerable<Employee>> GetEmployeesAsync(CancellationToken ct = default) {
            // Return your data here
        }
    }
}
csharp
public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        // ...
        services.AddScoped<NwindDataService>();
    }
}

Run Demo: TagBox - Empty Data Area Template