Search code examples
blazorblazor-server-sideblazor-webassembly

blazor render fragment doesn't refresh


I have a modal component in Blazor and it is possible to use it many times in a page, so when I use it more than one time in a page, for the second time the data doesn't refresh and it still shows the old data from first modal so it always shows me the Hello for all modal in the page, here is the Modal Component

     @inject IJSRuntime JsRuntime
    
    <dialog id="@ElementIds.Modal" class="modal">
        <div class="modal-box w-11/12 max-w-2xl">
            <div class="modal-action" style="margin: 10px">
                <form id="@ElementIds.ModalClose" method="dialog">
                    <!-- if there is a button, it will close the modal -->
                    <button class="btn btn-circle">
                        <svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" id="Close">
                            <path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M15.7,14.3c0.4,0.4,0.4,1,0,1.4c-0.4,0.4-1,0.4-1.4,0
                                    L12,13.4l-2.3,2.3c-0.4,0.4-1,0.4-1.4,0c-0.4-0.4-0.4-1,0-1.4l2.3-2.3L8.3,9.7c-0.4-0.4-0.4-1,0-1.4c0.4-0.4,1-0.4,1.4,0l2.3,2.3
                                    l2.3-2.3c0.4-0.4,1-0.4,1.4,0c0.4,0.4,0.4,1,0,1.4L13.4,12L15.7,14.3z" fill="#717af7" class="color000000 svgShape"></path>
                        </svg>
                    </button>
                </form>
            </div>
    
            <div class="h-full px-3 pb-4 overflow-y-auto ">
                @Content
            </div>
    
    
        </div>
    </dialog>
    
    @code {
        [Parameter]
        public  RenderFragment? Content { get; set; }
        
        internal static class ElementIds
        {
            public static Guid Modal { get; } = Guid.NewGuid();
            public static Guid ModalClose { get; } = Guid.NewGuid();
        }
        
        public void ShowModal()
        {
            _ = JsRuntime.InvokeVoidAsync("eval", $"document.getElementById('{ElementIds.Modal}').showModal()");
        }
        
        public void CloseModal()
        {
            _= JsRuntime.InvokeVoidAsync("eval", $"document.getElementById('{ElementIds.ModalClose}').submit()");
       

     }
    }

and for example, I use it like this (it's an example and sometimes I put table or form inside the modal)

    <button @onclick="()=>_modalRef.ShowModal()" class="btn avatar" style="position: absolute;bottom: 0;right: 40px; background: red">click</button>
    <Modal @ref="@_modalRef">
        <Content >
            <h1>hello</h1>
        </Content>
    </Modal>
    
    <button @onclick="()=>_modalRef.ShowModal()" class="btn avatar" style="position: absolute;bottom: 0;right: 40px; background: red">click</button>
    <Modal @ref="@_modalRef">
        <Content >
            <h1>hello message 1</h1>
        </Content>
    </Modal>
    
    @code{
    
        private Modal _modalRef;
    
    }

Solution

  • You correctly have IDs for the component but they are incorrectly declared as static. That means all <Modal> components will share the same IDs.

    internal class ElementIds
    {
        public Guid Modal { get; } = Guid.NewGuid();
        public Guid ModalClose { get; } = Guid.NewGuid();
    }
    
    private ElementIds ElementIds { get; } = new();