elektra
elektra

Reputation: 115

How to send data from Child to Parent component in Blazor (when a list is clicked)

I have a simple component like this:

@foreach(book in store) {
    <li @click="@SelectBook(@book.id)"> @book.title <li> <!-- book.id throws error -->
}

@code{
    [Parameter]
    public EventCallback<MouseEventArgs> OnBookSelected { get; set; }
   

   public async Task SelectBuild(MouseEventArgs e)
    {
        await OnBuildSelected.InvokeAsync(e); 
    }
}

On the parent side, I call the component as:

<Book @OnBookSelected="OnBuildSelectedHandler"></Book>

@code{
    public void OnBuildSelectedHandler(MouseEventArgs e)
    {
       // assign to variable to display in html
    }
} 

As you can some, I am using EventCallback and InvokeAsync from what I read to do. If I don't provide an arg SelectBook I get the event arg in parent, the the event arg e does not contain the book id, just some windows properties.

How do I get the clicked Book Id from child to parent?

Thanks

Upvotes: 2

Views: 2896

Answers (1)

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30001

Here's a slightly modified version of @Enet's answer that demonstrates how to use the built in razor bind framework used in the out-of-the-box Blazor input controls.

The modified BookComponent:

<ul>
    @foreach (var book in Books)
    {
        <li class="@this.Selected(book)" @key="book" @onclick="@(() => this.SelectBook(book))"> @book.Title</li>
    }
</ul>
@code
{
    [Parameter] public Book Value { get; set; }
    [Parameter] public EventCallback<Book> ValueChanged { get; set; }
    [Parameter, EditorRequired] public List<Book> Books { get; set; }

    public async Task SelectBook(Book book)
        => await ValueChanged.InvokeAsync(book);

    // If you want to highlight the selected book
    private string Selected(Book item)
        => item.ID == this.Value.ID
        ? "selected"
        : string.Empty;
}

And used like this:

@page "/"

<PageTitle>Index</PageTitle>

@if (_selectedBook != null)
{
    <div>@_selectedBook.Title </div>
}

<BookComponent Books="books" @bind-Value=this._selectedBook />

@code
{
    private List<Book> books = Enumerable.Range(1, 10)
        .Select(i => new Book {ID = i, Title = $"Title{i}"}).ToList();

    private Book? _selectedBook;
}

Upvotes: 2

Related Questions