Search code examples
c#asp.net-coreblazor

Why is modal not returning the Contact object selected? I'm getting a compile time error


I'm getting an error message trying to compile my modal example

Error (active) CS1503
Argument 2: cannot convert from 'method group' to 'Microsoft.AspNetCore.Components.EventCallback' BlazorApp1 C:\Users\rodchar\source\repos\ARLAppRegistration\BlazorApp1\Pages\Model-Test.razor 5

modal-test.razor:

@page "/modal-test"

<button @onclick="OpenModal">Open Modal</button>

<Modal OnSave="HandleSave" @ref="modal"></Modal>

<p>Selected contact: @SelectedContact?.Name</p>

@code {
    private Modal modal;
    private Contact SelectedContact;

    private void OpenModal()
    {
        modal?.Open();
    }

    private void HandleSave(Contact contact)
    {
        SelectedContact = contact;
    }

    public class Contact
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

modal.razor:

@page "/modal"

<div class="modal @ModalClass" tabindex="-1" role="dialog" style="display:@ModalDisplay" aria-labelledby="modalTitle" aria-describedby="modalBody" aria-hidden="@(!ShowBackdrop)">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="modalTitle">Select a Contact</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close" @onclick="Close">
                    <span aria-hidden="true">×</span>
                </button>
            </div>
            <div class="modal-body" id="modalBody">
                <ul>
                    @foreach (var contact in Contacts)
                    {
                        <li @onclick="() => SelectContact(contact)">@contact.Name</li>
                    }
                </ul>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="Close">Close</button>
            </div>
        </div>
    </div>
</div>

@if (ShowBackdrop)
{
    <div class="modal-backdrop fade show"></div>
}

@code {
    public string ModalDisplay { get; set; } = "none;";
    public string ModalClass { get; set; } = "";
    public bool ShowBackdrop { get; set; } = false;

    [Parameter]
    public EventCallback<Contact> OnSave { get; set; }

    private List<Contact> Contacts = new List<Contact>
    {
        new Contact { Id = 1, Name = "John Doe" },
        new Contact { Id = 2, Name = "Jane Smith" },
        new Contact { Id = 3, Name = "Bob Johnson" }
    };

    public void Open()
    {
        ModalDisplay = "block;";
        ModalClass = "show";
        ShowBackdrop = true;
        StateHasChanged();
    }

    public void Close()
    {
        ModalDisplay = "none";
        ModalClass = "";
        ShowBackdrop = false;
        StateHasChanged();
    }

    private async Task SelectContact(Contact contact)
    {
        if (OnSave.HasDelegate)
        {
            await OnSave.InvokeAsync(contact);
        }
        Close();
    }

    public class Contact
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

Solution

  • You define Contact in both the Modal and Modal-Test pages. You pass a Modal.Contact object in the callback, while HandleSave expects a Modal_Test.Contact. Hence the error. Define Contact once outside the two components.

    A comment: There's probably no reason for @page "/modal", as it's unlikely to be a route.