egil / Htmxor

Supercharges Blazor static server side rendering (SSR) by seamlessly integrating the Htmx.org frontend library.
MIT License
127 stars 13 forks source link

Active Search #65

Closed genifycom closed 1 month ago

genifycom commented 1 month ago

Hi Egil,

I am trying to get the active search https://htmx.org/examples/active-search/ working with Blazor SSR.

While I can get the POST request in the Blazor OnInitialized, I cannot seem to find the Body. HtmxRequest does not have it.

When using the HTMX element (hard to find any detailed documentation on input with hx-post)

<input class="form-control" type="search" name="search" placeholder="Begin Typing To Search Customers..."  
       hx-post="/examples/active-search"  
       hx-trigger="input changed delay:500ms, search"  
       hx-target="#search-results"  
       hx-indicator=".htmx-indicator">

then it appears that the POST body contains e.g. "search=a".

Trying to get that value.

Do you have any code for this one?

Thanks, Dave

genifycom commented 1 month ago

Ok, got it all working. Don't want to mess up your project, but here is the working page. Woohoo!

Love the idea. Blazor SSR is crucial to me because of running SSR in AWS Lambda serverless.

In such a scenario (which I have been using successfully for numerous client projects) only supports SSR. There is no SignalR or Blazor WASM in the AWS Serverless environment.

To fully render this page, you will need bars.svg in folder img under wwwroot to see the searching icon. Not sure if line three (the HtmxRoute) is needed.

@inherits ConditionalComponentBase
@page "/examples/active-search"
@attribute [HtmxRoute("/examples/active-search", Methods = [HttpMethods.Post])]

<PageTitle>Htmxor - Examples - Active Search</PageTitle>
<h1>Active Search</h1>
<p>This is a Htmxor version of the <a href="https://htmx.org/examples/active-search/" title="Active Search example">Active Search</a> example at htmx.org.</p>

<h3>
    Search Contacts
    <span class="htmx-indicator">
        <img src="/img/bars.svg" /> Searching...
    </span>
</h3>

<input class="form-control" type="search" name="search" placeholder="Begin Typing To Search Customers..."
       hx-post="/examples/active-search"
       hx-trigger="input changed delay:500ms, search"
       hx-target="#search-results"
       hx-indicator=".htmx-indicator">

<table class="table">
    <thead>
        <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Email</th>
            <th>Status</th>
        </tr>
    </thead>
    <tbody id="search-results">
        <HtmxFragment>
            @foreach (var contact in data)
            {
                <tr>
                    <td>@contact.FirstName</td>
                    <td>@contact.LastName</td>
                    <td>@contact.Email</td>
                </tr>
            }
        </HtmxFragment>
    </tbody>
</table>

@code {
    [SupplyParameterFromForm] //The input tag with hx-post posts a body containing the string (using the name attribute)
    private string search { get; set; } = string.Empty;

    private IEnumerable<Contact> data = Enumerable.Empty<Contact>();

    protected override void OnInitialized()
    {
        Thread.Sleep(1000); //Simulate a delay in order to show the searching icon
        data = string.IsNullOrEmpty(search)
            ? Contacts.Data.Values.Take(30)
           : Contacts.Data.Values.Where(c => (c.FirstName + " " + c.LastName).Contains(search, StringComparison.InvariantCultureIgnoreCase));
    }
}
egil commented 1 month ago

Nice, feel free to submit a PR with your implementation. Do suggest you change OnInitialized to OnInitializedAsync and use await Task.Delay(1000); instead, as Thread.Sleep(1000); blocks a thread.