Skip to content

Latest commit

 

History

History
177 lines (137 loc) · 5.06 KB

File metadata and controls

177 lines (137 loc) · 5.06 KB

FastComponents API Simplification

🎯 Simplified API Comparison

Before: Current Complex API

1. Component Creation (4+ files needed)

// CounterExample.razor.cs
[GenerateParameterMethods]
public partial record CounterParameters : HtmxComponentParameters
{
    public int Count { get; init; } = 10;
    
    public string Increment()
    {
        var parameters = this with { Count = Count + 1 }; 
        return parameters.ToComponentUrl(HtmxRoutes.RouteCounter);
    }
}

// HtmxRoutes.cs
public const string RouteCounter = "/ui/examples/counter";

// HtmxEndpointConfiguration.cs  
app.MapHtmxGet<CounterExample, CounterParameters>(RouteCounter).AllowAnonymous();

// JsonSerializerContext.cs
[JsonSerializable(typeof(CounterParameters))]

2. Component Template

@inherits HtmxComponentBase<CounterParameters>

<div class="counter-section" id="counter-component">
  <div class="grid">
    <HtmxTag Element="button"
             HxGet="@Parameters.Increment()"
             HxSwap="@Hx.Swap.OuterHtml"
             HxTarget="#counter-component">
      + Increment
    </HtmxTag>
    
    <input value="@Parameters.Count" readonly/>
  </div>
</div>

After: Simplified API

1. Component Creation (1 file only!)

@inherits SimpleHtmxComponent<CounterState>

<div id="counter">
  <div class="grid">
    @HtmxBuilderExtensions.Button("+", Url(s => s with { Count = s.Count + 1 }), "counter")
    <span>@State.Count</span>
    @HtmxBuilderExtensions.Button("-", Url(s => s with { Count = s.Count - 1 }), "counter")
  </div>
</div>

public record CounterState { public int Count { get; init; } = 0; }

2. Registration (1 line!)

// Program.cs
services.AddFastComponentsAuto();  // Replaces manual service registration
app.UseFastComponentsAuto();       // Replaces manual endpoint mapping

🚀 Key Improvements

1. Reduced Boilerplate by 80%

  • ❌ No more separate .razor.cs files
  • ❌ No more [GenerateParameterMethods] attributes
  • ❌ No more manual endpoint mapping
  • ❌ No more JSON serialization registration
  • ✅ Convention-based routing: /htmx/counter
  • ✅ Auto-discovery of components

2. Fluent Builder API

// Before: Verbose HtmxTag syntax
<HtmxTag Element="button" HxGet="/url" HxTarget="#target" HxSwap="outerHTML">

// After: Fluent builder
@HtmxBuilder.Button().GetSelf("/url", "target").Text("Click me")

// Or helper methods for common patterns
@HtmxBuilderExtensions.Button("Click me", "/url", "target")
@HtmxBuilderExtensions.SearchInput("/search", "#results")
@HtmxBuilderExtensions.LoadContainer("/load-content")

3. Smart Defaults & Patterns

// Common patterns made simple
HtmxPatterns.SelfUpdatingButton(url, id)     // Button that updates itself
HtmxPatterns.SearchInput(url, target)        // Search with debouncing
HtmxPatterns.LoadOnce(url)                   // Load content once on page load

// Smart defaults
HtmxDefaults.Swap                            // "outerHTML"
HtmxDefaults.SearchTrigger                   // "keyup changed delay:300ms"
HtmxDefaults.LoadOnceTrigger                 // "load once"

4. Type-Safe State Management

// Before: Complex parameter methods
public string Increment()
{
    var parameters = this with { Count = Count + 1 }; 
    return parameters.ToComponentUrl(HtmxRoutes.RouteCounter);
}

// After: Simple lambda expressions
Url(s => s with { Count = s.Count + 1 })    // Much cleaner!
Url(new CounterState { Count = State.Count + 1 })  // Or explicit

🎯 Migration Path

Phase 1: Backwards Compatible

  • Keep existing HtmxComponentBase<T> API
  • Add new SimpleHtmxComponent<T> alongside
  • Add convention-based registration as opt-in

Phase 2: Gradual Adoption

  • Migrate examples to simplified API
  • Show performance/maintainability benefits
  • Provide migration tooling

Phase 3: Stabilization

  • Mark old API as [Obsolete] but still supported
  • Focus documentation on simplified API
  • Community feedback integration

🔥 Developer Experience Benefits

For Beginners

  • 5-minute setup - Add components, registration is automatic
  • No magic - Clear, convention-based patterns
  • Less to learn - Focus on HTMX concepts, not FastComponents boilerplate

For Experts

  • Less maintenance - Fewer files, less configuration
  • Better debugging - Simpler call stacks, clearer errors
  • Higher productivity - Build components faster

Common Use Cases Made Trivial

// Counter component
@HtmxBuilderExtensions.Button("+", Url(s => s with { Count = s.Count + 1 }), "counter")

// Search component  
@HtmxBuilderExtensions.SearchInput("/search", "#results", "Search movies...")

// Auto-loading content
@HtmxBuilderExtensions.LoadContainer("/load-data", "Loading...")

// Form that posts to server
@HtmxBuilder.Form().PostTo("/submit", "#result").Content(@<input name="data" />)

This simplified API maintains all the power of FastComponents while dramatically reducing complexity for developers!