EasyAppDev.Blazor.AutoComplete
1.0.7
dotnet add package EasyAppDev.Blazor.AutoComplete --version 1.0.7
NuGet\Install-Package EasyAppDev.Blazor.AutoComplete -Version 1.0.7
<PackageReference Include="EasyAppDev.Blazor.AutoComplete" Version="1.0.7" />
<PackageVersion Include="EasyAppDev.Blazor.AutoComplete" Version="1.0.7" />
<PackageReference Include="EasyAppDev.Blazor.AutoComplete" />
paket add EasyAppDev.Blazor.AutoComplete --version 1.0.7
#r "nuget: EasyAppDev.Blazor.AutoComplete, 1.0.7"
#:package EasyAppDev.Blazor.AutoComplete@1.0.7
#addin nuget:?package=EasyAppDev.Blazor.AutoComplete&version=1.0.7
#tool nuget:?package=EasyAppDev.Blazor.AutoComplete&version=1.0.7
Blazor AutoComplete
A high-performance, feature-rich AutoComplete component for Blazor applications with AI-powered semantic search capabilities.
Features
- High Performance: Virtualization support for 100K+ items, < 100ms filter response time
- Lightweight: Core package 32KB Brotli / 41KB Gzip (completely inlined during trimming - 61% app size reduction)
- Native AOT Ready: Zero reflection, fully trimmable, source generators for build-time compilation
- AI-Powered Search: Semantic search via Microsoft.Extensions.AI with SIMD acceleration
- Accessibility: ~95% WCAG 2.1 AA compliant, comprehensive screen reader support, ARIA 1.2 Combobox pattern, live regions
- Flexible Theming: 4 design systems (Material, Fluent, Modern, Bootstrap), 9 Bootstrap color variants, 51 CSS variables
- Developer Friendly: Fluent API, 7 built-in display modes, IntelliSense-friendly, multi-field search
- Multi-Framework: .NET 8 LTS + .NET 9 support
- All Blazor Modes: WebAssembly, Server, Auto/United
Quick Start
Installation
dotnet add package EasyAppDev.Blazor.AutoComplete
Setup
Blazor WebAssembly (Standalone)
Add references to wwwroot/index.html:
<head>
<link href="_content/EasyAppDev.Blazor.AutoComplete/styles/autocomplete.base.css" rel="stylesheet" />
<script src="_content/EasyAppDev.Blazor.AutoComplete/scripts/theme-loader.js"></script>
</head>
Blazor Web App (.NET 8/9) - Server, Auto, or WebAssembly Rendering
Add references to Components/App.razor (or App.razor depending on your project structure):
<head>
<link href="_content/EasyAppDev.Blazor.AutoComplete/styles/autocomplete.base.css" rel="stylesheet" />
<script src="_content/EasyAppDev.Blazor.AutoComplete/scripts/theme-loader.js"></script>
</head>
Notes:
- The base CSS contains structural styles only (~8KB). Theme presets are loaded dynamically on-demand when you set the
ThemePresetparameter, resulting in optimal bundle size (~10KB total for base + one theme). - For Interactive WebAssembly or Interactive Auto render modes with a
.Clientproject, ensure the package is referenced in both the server and client projects.
Basic Usage
@using EasyAppDev.Blazor.AutoComplete
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct"
Placeholder="Search products..." />
@code {
private List<Product> products = new()
{
new Product { Id = 1, Name = "Apple" },
new Product { Id = 2, Name = "Banana" },
new Product { Id = 3, Name = "Cherry" }
};
private Product? selectedProduct;
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
Core Features
1. Multi-Field Search
Search across multiple properties simultaneously with ANY filter strategy (StartsWith, Contains, Fuzzy):
<AutoComplete TItem="Product"
Items="@products"
SearchFields="@(p => new[] { p.Name, p.Description, p.Category, p.Tags })"
FilterStrategy="FilterStrategy.Contains"
@bind-Value="@selectedProduct" />
How it works:
- Searches ALL specified fields in parallel
- Returns item if ANY field matches (OR logic)
- Works with all filter strategies including Fuzzy matching
- Takes precedence over TextField parameter
2. Built-In Display Modes
Eliminate 10-20 lines of repetitive ItemTemplate markup with 7 built-in display modes:
@using EasyAppDev.Blazor.AutoComplete.Options
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
DisplayMode="ItemDisplayMode.Simple"
@bind-Value="@selectedProduct" />
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
DescriptionField="@(p => p.Category)"
DisplayMode="ItemDisplayMode.TitleWithDescription"
@bind-Value="@selectedProduct" />
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
BadgeField="@(p => $"${p.Price}")"
BadgeClass="badge bg-success"
DisplayMode="ItemDisplayMode.TitleWithBadge"
@bind-Value="@selectedProduct" />
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
IconField="@(p => p.Emoji)"
DescriptionField="@(p => p.Category)"
DisplayMode="ItemDisplayMode.IconTitleDescription"
@bind-Value="@selectedProduct" />
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
IconField="@(p => p.Emoji)"
SubtitleField="@(p => p.Category)"
DescriptionField="@(p => p.Description)"
BadgeField="@(p => $"${p.Price}")"
BadgeClass="badge bg-success"
DisplayMode="ItemDisplayMode.Card"
@bind-Value="@selectedProduct" />
Available Display Modes:
- Simple - Just TextField value
- TitleWithDescription - Two-line (bold title + muted description)
- TitleWithBadge - Title with right-aligned badge
- TitleDescriptionBadge - Title + description + badge
- IconWithTitle - Icon/emoji on left + title
- IconTitleDescription - Icon + title + description
- Card - Card-style with all fields (icon, title, subtitle, description, badge)
Note: When DisplayMode is set to Custom (default), the component uses ItemTemplate if provided, otherwise falls back to Simple mode.
3. Filtering Strategies
Three built-in filter strategies with multi-field support:
<AutoComplete FilterStrategy="FilterStrategy.StartsWith" ... />
<AutoComplete FilterStrategy="FilterStrategy.Contains" ... />
<AutoComplete FilterStrategy="FilterStrategy.Fuzzy" ... />
<AutoComplete FilterStrategy="FilterStrategy.Custom"
CustomFilter="@myCustomFilter" ... />
Filter Performance (100K items):
- StartsWith: ~3ms (baseline, fastest)
- Contains: ~2ms (optimized substring search)
- Fuzzy: ~72ms (Levenshtein distance with word-level matching)
Fuzzy Filter Features:
- Default tolerance: 2 character edits (insertions, deletions, substitutions)
- Word-level matching: Splits on spaces/hyphens/underscores for better partial matches
- Example: "aple" → "apple" (1 edit) ✓ Match
4. Fluent Configuration API
Build complex configurations with method chaining:
var config = AutoCompleteConfig<Product>.Create()
.WithItems(products)
.WithTextField(p => p.Name)
.WithSearchFields(p => new[] { p.Name, p.Description, p.Category })
.WithTheme(Theme.Auto)
.WithBootstrapTheme(BootstrapTheme.Primary)
.WithDisplayMode(ItemDisplayMode.TitleWithDescription)
.WithTitleAndDescription(p => p.Description)
.WithVirtualization(threshold: 1000, itemHeight: 45)
.WithGrouping(p => p.Category)
.WithDebounce(500)
.Build();
Usage:
<AutoComplete TItem="Product" Config="@config" />
Benefits:
- 100% configuration coverage (52 parameters)
- Auto-generated via source generator (no manual errors)
- IntelliSense-friendly with method chaining
- Config parameter takes precedence over individual parameters
Note: The Config parameter relies on a source generator (ConfigurationApplierGenerator) that may not always generate code correctly. If you encounter issues where the fluent configuration doesn't work (no results shown), use individual parameters instead as a workaround. See [Issue #TBD] for more details.
5. Grouping
Group items by any property with custom headers:
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
GroupBy="@(p => p.Category)"
@bind-Value="@selectedProduct">
<GroupTemplate Context="group">
<strong>@group.Key</strong> <span class="badge">@group.Count()</span>
</GroupTemplate>
</AutoComplete>
Features:
- Groups maintain insertion order
- Custom group header templates
- Works with all filter strategies and display modes
6. Virtualization
Handle massive datasets (100K+ items) with ease:
<AutoComplete TItem="Product"
Items="@largeDataset"
TextField="@(p => p.Name)"
Virtualize="true"
VirtualizationThreshold="1000"
ItemHeight="45"
@bind-Value="@selectedProduct" />
Performance Benefits:
- Reduces DOM by 95%+ for large datasets
- 60fps scrolling maintained
- Automatic activation when items >= threshold
- Uses Blazor's built-in
<Virtualize>component
7. Async Data Source
Fetch data from remote APIs with cancellation support:
<AutoComplete TItem="Product"
DataSource="@productDataSource"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct" />
@code {
private IAutoCompleteDataSource<Product> productDataSource = new RemoteDataSource<Product>(
async (query, ct) =>
{
var response = await httpClient.GetFromJsonAsync<List<Product>>(
$"/api/products?q={query}", ct);
return response ?? Enumerable.Empty<Product>();
}
);
}
Features:
- Full
CancellationTokensupport (cancels old searches when user types rapidly) - Debouncing (default 300ms, configurable via
DebounceMs) - Loading state with
LoadingTemplate
8. Custom Templates
Override default rendering with custom templates:
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct">
<ItemTemplate Context="product">
<div class="product-item">
<img src="@product.ImageUrl" alt="@product.Name" />
<div>
<strong>@product.Name</strong>
<span class="price">$@product.Price</span>
<small class="text-muted">@product.Category</small>
</div>
</div>
</ItemTemplate>
<NoResultsTemplate>
<div class="text-center py-3">
<i class="bi bi-search"></i>
<p>No products found. Try a different search term.</p>
</div>
</NoResultsTemplate>
<LoadingTemplate>
<div class="text-center py-3">
<div class="spinner-border text-primary" role="status"></div>
<p>Searching products...</p>
</div>
</LoadingTemplate>
</AutoComplete>
Available Templates:
- ItemTemplate - Custom item rendering
- NoResultsTemplate - Custom no results message
- LoadingTemplate - Custom loading indicator
- HeaderTemplate - Header above list
- FooterTemplate - Footer below list
- GroupTemplate - Custom group header rendering
AI-Powered Semantic Search
Add intelligent semantic search that understands meaning, not just keywords. Users can search using natural language, synonyms, and concepts - perfect for technical documentation, product catalogs, and knowledge bases.
Installation
The AI package is optional and separate from the core component:
# Core component (required)
dotnet add package EasyAppDev.Blazor.AutoComplete
# AI semantic search (optional - includes core automatically)
dotnet add package EasyAppDev.Blazor.AutoComplete.AI
Note: Installing the AI package automatically installs the core package as a dependency.
Supported AI Providers
| Provider | Status | Setup Method | Cost | Privacy |
|---|---|---|---|---|
| OpenAI | ✅ Built-in | AddAutoCompleteSemanticSearch() |
$ | Cloud |
| Azure OpenAI | ✅ Built-in | AddAutoCompleteSemanticSearchWithAzure() |
$ | Azure Cloud |
| Ollama | ⚠️ Manual setup | Custom IEmbeddingGenerator |
Free | 100% Local |
| Custom | ✅ Supported | Any IEmbeddingGenerator<string, Embedding<float>> |
Varies | Varies |
Quick Start - OpenAI
1. Get an OpenAI API Key
- Sign up at https://platform.openai.com/
- Navigate to API Keys: https://platform.openai.com/api-keys
- Click "Create new secret key"
- Copy the key (starts with
sk-)
2. Configure API Key (3 options)
Option A: appsettings.json (Recommended)
{
"OpenAI": {
"ApiKey": "sk-proj-...",
"Model": "text-embedding-3-small"
}
}
// Program.cs
builder.Services.AddAutoCompleteSemanticSearch(builder.Configuration);
Option B: User Secrets (Development)
dotnet user-secrets init
dotnet user-secrets set "OpenAI:ApiKey" "sk-proj-..."
dotnet user-secrets set "OpenAI:Model" "text-embedding-3-small"
// Program.cs
builder.Services.AddAutoCompleteSemanticSearch(builder.Configuration);
Option C: Direct API Key (Quick Testing)
// Program.cs
builder.Services.AddAutoCompleteSemanticSearch(
apiKey: "sk-proj-...",
model: "text-embedding-3-small"); // Optional, defaults to "text-embedding-3-small"
3. Use in Component
@using EasyAppDev.Blazor.AutoComplete.AI
<SemanticAutoComplete TItem="TechDoc"
Items="@docs"
SearchFields="@(d => new[] { d.Title, d.Description, d.Tags })"
TextField="@(d => d.Title)"
SimilarityThreshold="0.15"
@bind-Value="@selectedDoc"
Placeholder="Search by meaning..." />
@code {
private List<TechDoc> docs = new()
{
new TechDoc { Title = "Authentication Best Practices", Description = "OAuth2, JWT, and API security" },
new TechDoc { Title = "React Native Tutorial", Description = "Build mobile apps with React" },
new TechDoc { Title = "Async/Await Patterns", Description = "Asynchronous programming in C#" }
};
private TechDoc? selectedDoc;
}
public class TechDoc
{
public string Title { get; set; } = "";
public string Description { get; set; } = "";
public string Tags { get; set; } = "";
}
Azure OpenAI Setup
1. Create Azure OpenAI Resource
- Navigate to https://portal.azure.com
- Create an Azure OpenAI resource
- Deploy an embedding model (e.g.,
text-embedding-ada-002)
2. Get Credentials
- Endpoint:
https://YOUR-RESOURCE-NAME.openai.azure.com/ - API Key: Found in "Keys and Endpoint" section
- Deployment Name: The name you gave your deployed model
3. Configure
// Program.cs
builder.Services.AddAutoCompleteSemanticSearchWithAzure(
endpoint: "https://my-resource.openai.azure.com/",
apiKey: "your-azure-api-key",
deploymentName: "text-embedding-ada-002");
Ollama Setup (Local, Privacy-Focused)
For 100% local/offline semantic search with no API costs:
1. Install Ollama
# macOS/Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows: Download from https://ollama.com/download
2. Pull Embedding Model
ollama pull nomic-embed-text
3. Install OllamaSharp
dotnet add package OllamaSharp
4. Configure Custom Provider
// Program.cs
using OllamaSharp;
using Microsoft.Extensions.AI;
var ollamaClient = new OllamaApiClient("http://localhost:11434");
builder.Services.AddSingleton<IEmbeddingGenerator<string, Embedding<float>>>(
ollamaClient.AsEmbeddingGenerator("nomic-embed-text"));
See samples/AI-Examples/OllamaExample.cs for complete example.
Available Embedding Models
OpenAI Models:
text-embedding-3-small(1536 dimensions) - Recommended - Best price/performancetext-embedding-3-large(3072 dimensions) - Highest qualitytext-embedding-ada-002(1536 dimensions) - Legacy, still supported
Azure OpenAI Models:
- Same models as OpenAI, deployed in your Azure subscription
Ollama Models (Local):
nomic-embed-text- Recommended - 768 dimensions, optimized for retrievalall-minilm- 384 dimensions, smaller/fastermxbai-embed-large- 1024 dimensions, higher quality
How Semantic Search Works
Traditional Text Search:
Query: "mobile apps"
Matches: Items containing exact words "mobile" OR "apps"
Semantic Search:
Query: "mobile apps"
Matches:
- "React Native Tutorial" (mentions mobile development)
- "Flutter Guide" (mobile framework)
- "Progressive Web Apps" (web-based mobile)
- "iOS Development" (mobile platform)
Behind the Scenes:
- Embedding Generation: Text → 1536-dimensional vector representing meaning
- Similarity Calculation: SIMD-accelerated cosine similarity (3-5x faster)
- Dual Caching:
- Item cache (1 hour TTL): Stores embeddings for all items
- Query cache (15 min TTL): Stores embeddings for user queries
- Hybrid Fallback: Short queries (< 3 chars) use traditional text matching
Advanced Configuration
Cache Tuning for Large Datasets:
<SemanticAutoComplete TItem="Product"
Items="@products"
SearchFields="@(p => new[] { p.Name, p.Description, p.Category })"
@* Cache Configuration *@
ItemCacheDuration="TimeSpan.FromHours(2)"
QueryCacheDuration="TimeSpan.FromMinutes(30)"
MaxItemCacheSize="20000"
MaxQueryCacheSize="2000"
@* Pre-warming (generate all embeddings on load) *@
PreWarmCache="true"
ShowCacheStatus="true" @* Shows "Cached: 1234/5000 (75% hit rate)" *@
@* Search Tuning *@
SimilarityThreshold="0.15" @* Lower = more results (0.0-1.0) *@
MinSearchLength="3" @* Min chars before semantic search *@
DebounceMs="500" @* Wait time before API call *@
@bind-Value="@selectedProduct" />
Performance Metrics:
- SIMD Acceleration: 3-5x faster similarity calculation
- Cache Hit Rate: Typical 80%+ after warm-up
- API Cost Reduction: 80%+ due to caching
- Parallel Pre-warming: 4 concurrent embedding requests
Troubleshooting
"Missing embedding generator" Error:
Error: Add services.AddAutoCompleteSemanticSearch(configuration) to Program.cs
Solution: Ensure you've registered the embedding service in Program.cs:
builder.Services.AddAutoCompleteSemanticSearch(builder.Configuration);
No Results Returned:
- Lower
SimilarityThreshold(try 0.1 instead of 0.15) - Check API key is valid
- Verify items have text in SearchFields
- Enable
ShowCacheStatus="true"to monitor cache
API Rate Limits:
- Enable caching:
ItemCacheDuration="TimeSpan.FromHours(1)" - Increase debounce:
DebounceMs="800" - Use pre-warming for batch operations
Search Examples
Query: "password security" Finds: "Authentication Best Practices", "OAuth Implementation", "JWT Tokens", "API Security"
Query: "mobile development" Finds: "React Native", "Flutter", "Progressive Web Apps", "iOS Development", "Android SDK"
Query: "async code" Finds: "Async/Await Patterns", "Task Parallel Library", "Asynchronous Programming", "Background Workers"
Query: "database optimization" Finds: "SQL Performance Tuning", "Index Optimization", "Query Optimization", "Database Caching"
Theming
Quick Start - Zero CSS Theming
Theme your autocomplete component without writing any CSS:
@using EasyAppDev.Blazor.AutoComplete.Options
<AutoComplete ThemePreset="ThemePreset.Material"
Items="@countries"
@bind-Value="selectedCountry" />
<AutoComplete PrimaryColor="#FF6B6B"
BorderRadius="8px"
FontFamily="Inter, sans-serif"
Items="@countries"
@bind-Value="selectedCountry" />
Theme Presets (Design Systems)
Choose from 4 professionally designed theme presets with dynamic CSS loading (~2KB each, loaded on-demand):
| Preset | Design System | Primary Color | Features |
|---|---|---|---|
| Material | Google Material Design 3 | Purple (#6200EE) | Elevation, Purple accent, Roboto font |
| Fluent | Microsoft Fluent Design | Blue (#0078D4) | Acrylic, Sharp corners, Segoe UI font |
| Modern | Minimal/Clean | Blue (#2563EB) | Flat, No shadows, System fonts |
| Bootstrap | Bootstrap 5 | Blue (#0D6EFD) | Familiar, rem units, Bootstrap colors |
@using EasyAppDev.Blazor.AutoComplete.Options
<AutoComplete ThemePreset="ThemePreset.Material"
Items="@products"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct" />
<AutoComplete ThemePreset="ThemePreset.Fluent"
Items="@products"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct" />
Key Features:
- ✅ Dynamic loading - Only active theme CSS loads (~10KB typical vs 16KB for all themes)
- ✅ Automatic dark mode - All presets support
@media (prefers-color-scheme: dark) - ✅ Coordinated design - Colors, spacing, typography, and effects professionally matched
- ✅ Zero configuration - Just set
ThemePresetparameter
Bootstrap Color Variants
9 color variants for Bootstrap 5 integration:
<AutoComplete BootstrapTheme="BootstrapTheme.Primary" ... />
<AutoComplete BootstrapTheme="BootstrapTheme.Success" ... />
<AutoComplete BootstrapTheme="BootstrapTheme.Danger" ... />
<AutoComplete BootstrapTheme="BootstrapTheme.Warning" ... />
Available Variants: Default, Primary, Secondary, Success, Danger, Warning, Info, Light, Dark
Light/Dark Mode Toggle
<AutoComplete Theme="Theme.Light" ... />
<AutoComplete Theme="Theme.Dark" ... />
<AutoComplete Theme="Theme.Auto" ... />
Runtime Theme Switching
Switch themes dynamically with smooth transitions:
<AutoComplete TItem="Product"
ThemePreset="@currentTheme"
EnableThemeTransitions="true"
Items="@products"
TextField="@(p => p.Name)" />
<div class="theme-switcher">
<button @onclick="() => currentTheme = ThemePreset.Material">Material</button>
<button @onclick="() => currentTheme = ThemePreset.Fluent">Fluent</button>
<button @onclick="() => currentTheme = ThemePreset.Modern">Modern</button>
<button @onclick="() => currentTheme = ThemePreset.Bootstrap">Bootstrap</button>
</div>
@code {
private ThemePreset currentTheme = ThemePreset.Material;
}
Custom Theme Properties
Override 51 individual properties without writing CSS:
<AutoComplete ThemePreset="ThemePreset.Material"
PrimaryColor="#FF6B6B"
BorderRadius="8px"
FontFamily="Inter, sans-serif"
Items="@products"
@bind-Value="@selectedProduct" />
<AutoComplete PrimaryColor="#6200EE"
BackgroundColor="#FFFFFF"
TextColor="#1C1B1F"
BorderColor="#79747E"
BorderRadius="4px"
InputPadding="12px 16px"
FontFamily="Roboto, sans-serif"
FontSize="14px"
DropdownShadow="0 2px 8px rgba(0,0,0,0.15)"
Items="@products"
@bind-Value="@selectedProduct" />
Available Properties (51 total):
- Colors (15): Primary, Background, Text, TextSecondary, Border, BorderFocus, Hover, Selected, SelectedText, Disabled, Error, Shadow, DropdownBackground, Focus, Placeholder
- Spacing (10): InputPadding, ItemPadding, BorderRadius, DropdownGap, ItemGap, GroupHeaderPadding, MaxHeight, MinWidth, ListPadding, IconSize
- Typography (8): FontFamily, FontSize, LineHeight, FontWeight, DescriptionFontSize, BadgeFontSize, GroupHeaderFontSize, LetterSpacing
- Effects (5): FocusShadow, DropdownShadow, TransitionDuration, BorderWidth, TransitionTiming
- Individual Parameters (13): PrimaryColor, BackgroundColor, TextColor, BorderColor, HoverColor, SelectedColor, BorderRadius, FontFamily, FontSize, DropdownShadow (convenient shortcuts that override ThemeOverrides)
Component Size Variants
@using EasyAppDev.Blazor.AutoComplete.Options
<AutoComplete Size="ComponentSize.Compact" ... />
<AutoComplete Size="ComponentSize.Default" ... />
<AutoComplete Size="ComponentSize.Large" ... />
Accessibility
WCAG 2.1 AA Compliant (~95%) - Full ARIA 1.2 Combobox pattern with comprehensive screen reader support.
Keyboard Navigation
| Key | Action |
|---|---|
| ArrowDown/Up | Navigate items |
| Enter | Select item |
| Escape | Close dropdown |
| Home/End | First/last item |
| Tab | Close and move focus |
Key Features
Screen Reader Support:
- ✅ Live region announcements (loading, results, errors)
- ✅ Full ARIA attributes (aria-expanded, aria-activedescendant, aria-selected, aria-busy, aria-invalid)
- ✅ Tested with VoiceOver, NVDA, JAWS
Label Association:
<label for="search">Search:</label>
<AutoComplete InputId="search" Items="@items" ... />
Form Validation:
<EditForm Model="@model">
<AutoComplete @bind-Value="@model.Country"
ValueExpression="@(() => model.Country)" />
</EditForm>
Visual Accessibility:
- ✅ AAA contrast ratios (17.5:1 to 21:1)
- ✅
:focus-visiblefor keyboard-only navigation - ✅ High contrast mode support
- ✅ Reduced motion support
- ✅ Semantic HTML (
<ul>,<li>,<button>)
Compliance:
- ✅ 1.3.1 Info and Relationships (A)
- ✅ 2.1.1 Keyboard (A)
- ✅ 2.4.7 Focus Visible (AA)
- ✅ 3.3.2 Labels or Instructions (A)
- ✅ 4.1.2 Name, Role, Value (A)
- ✅ 4.1.3 Status Messages (AA)
AOT & Trimming Compatibility
Full Native AOT support with zero runtime reflection:
Source Generators (3 Total)
- PropertyAccessorGenerator - Generates compiled property accessors at build time
- ExpressionValidatorGenerator - Enforces trimming-safe expression patterns with diagnostics (EBDAC001-003)
- ConfigurationApplierGenerator - Auto-generates configuration application method (100% coverage)
Build-Time Validation
// ✅ VALID: Simple property access
<AutoComplete TextField="@(p => p.Name)" ... />
// ❌ INVALID: Method call - triggers EBDAC001 error
<AutoComplete TextField="@(p => p.Name.ToUpper())" ... />
// ❌ INVALID: String interpolation - triggers EBDAC001 error
<AutoComplete TextField="@(p => $\"{p.Name}\")" ... />
Diagnostic Codes:
- EBDAC001: Invalid TextField Expression (must be simple property access)
- EBDAC002: Invalid ValueField Expression
- EBDAC003: Unsupported Expression Type (trimming incompatible)
Publishing for AOT
dotnet publish -c Release /p:PublishAot=true
AOT-Safe Features:
- All expressions compiled at build time via source generators
- No runtime
Expression.Compile()calls - No reflection APIs used
- Fully trimmable with
IsTrimmable=true - Source generators target netstandard2.0 for analyzer compatibility
API Reference
Core Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Config |
AutoCompleteConfig<TItem>? |
null |
Fluent configuration object (when provided, takes precedence over individual parameters) |
Items |
IEnumerable<TItem>? |
null |
Collection of items to display |
DataSource |
IAutoCompleteDataSource<TItem>? |
null |
Async data source for remote data |
Value |
TItem? |
null |
Currently selected value (two-way binding) |
TextField |
Expression<Func<TItem, string>>? |
null |
Expression to extract display text |
SearchFields |
Expression<Func<TItem, string[]>>? |
null |
Multi-field search expression (takes precedence over TextField) |
Placeholder |
string? |
null |
Input placeholder text |
MinSearchLength |
int |
1 |
Minimum characters before searching |
MaxDisplayedItems |
int |
100 |
Maximum items to display |
AllowClear |
bool |
true |
Show clear button |
Disabled |
bool |
false |
Disable the component |
DebounceMs |
int |
300 |
Debounce delay in milliseconds |
CloseOnSelect |
bool |
true |
Close dropdown on selection |
AriaLabel |
string? |
null |
ARIA label for accessibility |
InputId |
string? |
null |
Explicit ID for input element (for label association) |
Filtering Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
FilterStrategy |
FilterStrategy |
StartsWith |
Filtering strategy (StartsWith, Contains, Fuzzy, Custom) |
CustomFilter |
IFilterEngine<TItem>? |
null |
Custom filter engine when FilterStrategy.Custom |
Display Mode Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
DisplayMode |
ItemDisplayMode |
Custom |
Built-in display mode (Simple, TitleWithDescription, TitleWithBadge, TitleDescriptionBadge, IconWithTitle, IconTitleDescription, Card, Custom) |
DescriptionField |
Expression<Func<TItem, string>>? |
null |
Property for description text |
BadgeField |
Expression<Func<TItem, string>>? |
null |
Property for badge text |
IconField |
Expression<Func<TItem, string>>? |
null |
Property for icon/emoji |
SubtitleField |
Expression<Func<TItem, string>>? |
null |
Property for subtitle (Card mode) |
BadgeClass |
string |
"badge bg-primary" |
CSS class for badge styling |
Theming Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Theme |
Theme |
Auto |
Color theme (Auto, Light, Dark) |
ThemePreset |
ThemePreset |
None |
Design system preset (Material, Fluent, Modern, Bootstrap) |
BootstrapTheme |
BootstrapTheme |
Default |
Bootstrap color variant (9 options) |
Size |
ComponentSize |
Default |
Component size (Compact, Default, Large) |
EnableThemeTransitions |
bool |
true |
Smooth theme transitions |
RightToLeft |
bool |
false |
RTL text direction |
ThemeOverrides |
ThemeOptions? |
null |
Structured theme customization |
PrimaryColor |
string? |
null |
Individual color override |
BackgroundColor |
string? |
null |
Individual color override |
TextColor |
string? |
null |
Individual color override |
BorderColor |
string? |
null |
Individual color override |
HoverColor |
string? |
null |
Individual color override |
SelectedColor |
string? |
null |
Individual color override |
BorderRadius |
string? |
null |
Individual spacing override |
FontFamily |
string? |
null |
Individual typography override |
FontSize |
string? |
null |
Individual typography override |
DropdownShadow |
string? |
null |
Individual effect override |
Virtualization Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Virtualize |
bool |
false |
Enable virtualization for large datasets |
VirtualizationThreshold |
int |
100 |
Minimum items before virtualization activates |
ItemHeight |
float |
40 |
Item height in pixels (required for virtualization) |
Grouping Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
GroupBy |
Expression<Func<TItem, object>>? |
null |
Expression to group items by property |
GroupTemplate |
RenderFragment<IGrouping<object, TItem>>? |
null |
Custom group header template |
Template Parameters
| Template | Type | Description |
|---|---|---|
ItemTemplate |
RenderFragment<TItem>? |
Custom item rendering |
NoResultsTemplate |
RenderFragment? |
Custom no results message |
LoadingTemplate |
RenderFragment? |
Custom loading indicator |
HeaderTemplate |
RenderFragment? |
Header above list |
FooterTemplate |
RenderFragment? |
Footer below list |
GroupTemplate |
RenderFragment<IGrouping<object, TItem>>? |
Group header rendering |
Events
| Event | Type | Description |
|---|---|---|
ValueChanged |
EventCallback<TItem?> |
Fired when selection changes (two-way binding) |
Form Integration
| Parameter | Type | Description |
|---|---|---|
ValueExpression |
Expression<Func<TItem?>>? |
Expression for validation integration |
EditContext |
EditContext? |
Cascading EditContext for form validation |
Browser Support
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- Mobile browsers (iOS Safari, Chrome Mobile)
Requirements
- .NET 8.0 or .NET 9.0
- Blazor WebAssembly, Server, or Auto/United
Packages
| Package | Version | Description | Size |
|---|---|---|---|
EasyAppDev.Blazor.AutoComplete |
Core component | 32KB Brotli / 41KB Gzip (inlined when trimmed) | |
EasyAppDev.Blazor.AutoComplete.Generators |
Source generators | 0KB runtime | |
EasyAppDev.Blazor.AutoComplete.AI |
AI integration | ~25KB (estimated) |
Architecture
SOLID Principles
The component follows SOLID principles with service-based architecture:
- Single Responsibility: Each class has one clear purpose (ThemeManager, FilterEngine, DisplayModeRenderer)
- Open/Closed: Extensible via strategies (IFilterEngine, IDisplayModeRenderer, IDataSource), closed for modification
- Liskov Substitution: All filters implement
IFilterEngine<TItem>, all data sources implementIAutoCompleteDataSource<TItem> - Interface Segregation: Small, focused interfaces (IFilterEngine has 2 methods)
- Dependency Inversion: Depends on abstractions (IFilterEngine, IDataSource) not concrete implementations
Service-Based Architecture
- ThemeManager - Theme application and CSS variable management
- FilterEngineBase<TItem> - Base class for all filtering strategies (StartsWith, Contains, Fuzzy, Custom)
- DisplayModeRendererFactory - Factory pattern for creating display mode renderers
- SemanticSearchDataSource - AI-powered semantic search with dual caching and SIMD acceleration
- EmbeddingCache<TItem> - Lock-free concurrent cache with LRU eviction
- KeyboardNavigationHandler - Keyboard navigation state and command pattern
- DebounceTimer - Debouncing utility for input throttling
Source Generators
Three source generators ensure AOT compatibility and developer productivity:
- PropertyAccessorGenerator - Generates compiled property accessors at build time
- ExpressionValidatorGenerator - Build-time expression validation with diagnostics
- ConfigurationApplierGenerator - Auto-generates configuration application (100% coverage)
Contributing
Contributions are welcome! Please read our Contributing Guide for details.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Acknowledgments
Built with:
Made with ❤️ by EasyAppDev
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.AspNetCore.Components.Web (>= 8.0.0)
-
net9.0
- Microsoft.AspNetCore.Components.Web (>= 9.0.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on EasyAppDev.Blazor.AutoComplete:
| Package | Downloads |
|---|---|
|
EasyAppDev.Blazor.AutoComplete.AI
AI-powered semantic search for Blazor AutoComplete using Microsoft.Extensions.AI. Supports OpenAI, Azure OpenAI, and Ollama with SIMD-accelerated similarity, dual caching (items + queries), and hybrid search. Includes core package. |
|
|
EasyAppDev.Blazor.AutoComplete.OData
OData integration for Blazor AutoComplete. Query OData v3/v4 endpoints with automatic $filter generation, multi-field search, and all filter strategies (StartsWith, Contains, Fuzzy). Includes core package. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version 1.0.7 - Added AOT-compatible JSON serialization overloads for all vector database providers. Fixed exception handling in GetItem to return default on deserialization failure. Added cancellation token propagation in Azure Search hybrid search. Improved robustness and trimming compatibility.