Kai
Kai

Reputation: 790

How to trigger page refreshes on input change in blazor app

I'm starting out with razor and trying to simply refresh my page with new data when I enter data in a search textbox.

My code - Component:

<div class="text-lg-start bg-blue-100">
    <input class="border-4 w-1/3 rounded m-6 p-6 h-8 border-blue-300" @bind-value="SearchText" @bind-value:event="oninput" placeholder="Search by title" />
    </div>
    <table class="table">
        <thead>
            <tr>
                <th>Btn</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var movie in movies)
            {
                <tr>
                    <td>
                        <button class="btn btn-danger" @onclick="() => Hire(movie)">Rent</button>
                    </td>
                </tr>
            }
        </tbody>
    </table>

@code {
    private Movie[]? movies;
    [Parameter]
    public string SearchText { get; set; } = "";
    async Task Hire(Movie movie)
    {
       protected override async Task OnInitializedAsync()
       {
           movies = await MovieService.GetMovies(SearchText);
       }
       protected override async void OnParametersSet()
       {
           movies = await MovieService.GetMovies(SearchText);
       }
   }

My code - Service:

 public class MovieService
 {
    private static readonly Movie[] MovieTest = new[]
    {
         new Movie(90, new List<string>(){"Horror"}, "The Skeleton Key"),
         new Movie(120, new List<string>(){ "Science Fiction"}, "Star Wars")
    };
    public Task<Movie[]> GetMovies(string? search = null)
    {
        return Task.FromResult(MovieTest);
    }
}

The only thing I want to achieve is that the screen gets refreshed based on what I put in the search box (typing 'SK' I would like to only see the skeleton key).

I found a working example where you filter the clientside data in the component, but I specifically wish to call the async service function, so that I can replace the body with an actual service call later. Anyone know what I am doing wrong or missing here?

P.S. I tried adding @page "/{SearchText: string}" besides my standard @page "/", but this causes a null-reference exception in the _Host.cshtml

Upvotes: 2

Views: 1388

Answers (1)

Dimitris Maragkos
Dimitris Maragkos

Reputation: 11392

You can use @onchange EventCallback to call your service when the input element loses focus:

<input class="..." value="@SearchText" @onchange="HandleChange" placeholder="Search by title" />

@code {
    private Movie[]? movies;

    [Parameter]
    public string? SearchText { get; set; }

    protected override async Task OnInitializedAsync()
    {
        movies = await MovieService.GetMovies(SearchText);
    }

    private async Task HandleChange(ChangeEventArgs e)
    {
        SearchText = e?.Value?.ToString();

        movies = await MovieService.GetMovies(SearchText);
    }
}

You can also use @oninput EventCallback in the same way:

<input class="..." value="@SearchText" @oninput="HandleChange" placeholder="Search by title" />

but this will trigger MovieService.GetMovies immediately after every input change, so you shouldn't use it if your service makes actual http calls to a backend server or queries to a database.

Use whichever fits best for you scenario.

Blazor data binding

Upvotes: 3

Related Questions