EasyAppDev.Blazor.AutoComplete.AI
1.0.2
See the version list below for details.
dotnet add package EasyAppDev.Blazor.AutoComplete.AI --version 1.0.2
NuGet\Install-Package EasyAppDev.Blazor.AutoComplete.AI -Version 1.0.2
<PackageReference Include="EasyAppDev.Blazor.AutoComplete.AI" Version="1.0.2" />
<PackageVersion Include="EasyAppDev.Blazor.AutoComplete.AI" Version="1.0.2" />
<PackageReference Include="EasyAppDev.Blazor.AutoComplete.AI" />
paket add EasyAppDev.Blazor.AutoComplete.AI --version 1.0.2
#r "nuget: EasyAppDev.Blazor.AutoComplete.AI, 1.0.2"
#:package EasyAppDev.Blazor.AutoComplete.AI@1.0.2
#addin nuget:?package=EasyAppDev.Blazor.AutoComplete.AI&version=1.0.2
#tool nuget:?package=EasyAppDev.Blazor.AutoComplete.AI&version=1.0.2
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
- EasyAppDev.Blazor.AutoComplete (>= 1.0.2)
- Microsoft.Extensions.AI.Abstractions (>= 10.0.1)
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.0)
- Microsoft.SemanticKernel (>= 1.67.1)
- Microsoft.SemanticKernel.Connectors.OpenAI (>= 1.67.1)
- System.Numerics.Tensors (>= 10.0.0)
-
net9.0
- EasyAppDev.Blazor.AutoComplete (>= 1.0.2)
- Microsoft.Extensions.AI.Abstractions (>= 10.0.1)
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.0)
- Microsoft.SemanticKernel (>= 1.67.1)
- Microsoft.SemanticKernel.Connectors.OpenAI (>= 1.67.1)
- System.Numerics.Tensors (>= 10.0.0)
NuGet packages (5)
Showing the top 5 NuGet packages that depend on EasyAppDev.Blazor.AutoComplete.AI:
| Package | Downloads |
|---|---|
|
EasyAppDev.Blazor.AutoComplete.AI.CosmosDb
Azure CosmosDB provider for EasyAppDev.Blazor.AutoComplete.AI semantic search. Provides multi-model database with DiskANN vector search for production-scale autocomplete scenarios with global distribution. |
|
|
EasyAppDev.Blazor.AutoComplete.AI.PostgreSql
PostgreSQL/pgvector provider for EasyAppDev.Blazor.AutoComplete.AI semantic search. Provides persistent vector storage with HNSW indexing for production-scale autocomplete scenarios. |
|
|
EasyAppDev.Blazor.AutoComplete.AI.Pinecone
Pinecone provider for EasyAppDev.Blazor.AutoComplete.AI semantic search. Provides serverless vector storage with high-performance similarity search for production-scale autocomplete scenarios. |
|
|
EasyAppDev.Blazor.AutoComplete.AI.AzureSearch
Azure AI Search provider for EasyAppDev.Blazor.AutoComplete.AI semantic search. Provides cloud-native vector search with hybrid (vector + keyword) search and semantic ranking support. |
|
|
EasyAppDev.Blazor.AutoComplete.AI.Qdrant
Qdrant provider for EasyAppDev.Blazor.AutoComplete.AI semantic search. Provides open-source vector storage with HNSW indexing for production-scale autocomplete scenarios. Supports self-hosted and cloud deployments. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version 1.0.2 - Streamlined documentation, security enhancements, and improved test coverage.