Search code examples
c#blazorblazorise

How to pass an ID parameter to Blazorise modal on button click, from one component to another?


I'm new and trying to formulate this as best as I can. There's so much new concepts to get a hold of! Please tell me if I'm unclear.

I'm making a Todo-app as an exercise. On page load I get todo items from the database and iterate them in a foreach-loop, each todo is assigned an X-button for removal. This was easy, but for modifying a todo text I want an update button that brings up Blazorise's modal popup, to use it's input field.

My problem is that I don't get how to pass each todo item's id into this modal, for each button that is. For the remove button I could use the foreach loop's "todoItem.Id" variable, but as the Blazorise modal is another component I can't.

Here's how my Index page looks:

@page "/"
@using TodoApp.App.Components

<section class="todo-container">
    @if (TodoItems != null)
    {
        @foreach (var todoItem in TodoItems)
        {
            if (todoItem.IsDone == false)
            {
                <div class="todo-item">
                    <p>@todoItem.Text</p>
                    <UpdatePopup OnTodoItemUpdated="UpdateAndLoad"></UpdatePopup>
                    <Button class="remove-btn" Clicked="(() => RemoveTodoItem(todoItem.Id))">X</Button>
                </div>
            }
        }
    }
</section>

<Popup OnTodoItemAdded="UpdateAndLoad"></Popup>

This button is inside the modal itself: <Button Clicked="@ShowModal">...</Button>, and I would've wanted to do the same thing as with the remove button, adding something like () => UpdateTodoItem(todoItem.Id).

How to get the ID from each item in the Index component and add this to each button in the Modal component?


Solution

  • There are multiple problems with your solution. First, you're creating a modal for each todo item (UpdatePopup) which is very inefficient. You should instead create just one update modal and use it for all the items.

    @page "/"
    @using TodoApp.App.Components
    
    <section class="todo-container">
        @if (TodoItems != null)
        {
            @foreach (var todoItem in TodoItems)
            {
                if (todoItem.IsDone == false)
                {
                    <div class="todo-item">
                        <p>@todoItem.Text</p>
                        <Button class="update-btn" Clicked="(() => updatePopupRef.Show(todoItem))">Edit</Button>
                        <Button class="remove-btn" Clicked="(() => RemoveTodoItem(todoItem.Id))">X</Button>
                    </div>
                }
            }
        }
    </section>
    
    <UpdatePopup @ref="@updatePopupRef" OnTodoItemUpdated="UpdateAndLoad" />
    
    <Popup OnTodoItemAdded="UpdateAndLoad" />
    @code{
    UpdatePopup updatePopupRef;
    }
    

    And then in UpdatePopup you have something like this:

    void Show(TodoItem item)
    {
        this.Item = item; // use this to bind item values to input fields
    
        modalRef.Show(); // you also need to have modalRef set with @ref attribute
    }
    

    and in razor

    <TextEdit @bind-Text="@Item.Name" />
    

    PS. I haven't tested this code but you should have an overall idea :)