Search code examples
c#dynamicblazor

Get Value From Dynamic Component in Blazor


I am trying to use the new dynamic component feature released in .net 6. I have watched all the videos on youtube and done the examples. I simply cant seem to figure how to get a value back from the component. I have used the Parameters Property of the dynamic component tied together with an event, but my use case will be to have a bunch of dynamic components loaded on to the page and the submit button is part of the parent page and not the dynamic components. When submit it clicked, I just want the value from the textbox dynamic component on the parent page. Heres an example :

TextBoxComponent

@Label: <input type="text" style="margin: 5px;" @bind-value="@TextBoxValue"/> 
@code{
    public string Label { get; set; }
    public string TextBoxValue { get;set; }
    protected override Task OnInitializedAsync()
    {
        return base.OnInitializedAsync();
    }
}

Index Page:

@page "/"
@if (type != null)
{
        <DynamicComponent Type="type"  />
}

<button class="btn btn-primary" @onclick="SaveToDatabase">Submit</button>

@code {
    Type type;

    protected async override Task OnInitializedAsync()
    {
        type = typeof(TextBoxComponent);
    }

    private void SaveToDatabase()
    {
        // get the text value of the dynamic component and insert into db
    }
}

I have tried creating an object called Appstate and assigning a string property but still I cant get the value.


Solution

  • For learning about Blazor, I recommend the official documentation. What I describe below comes directly from the documentation.

    I modified your example in 2 ways:

    1. One way is to use @ref to get a reference to the component and then access the TextBoxValue property. Once you have a reference to the component, you can get to the TextBoxValue property like this: (dc?.Instance as TextBoxComponent)?.TextBoxValue; *Note that the ? is because I am using nullable reference types.

    2. The second way is hooking up an EventCallBack by passing it through the Parameters parameter.

    I also added two text fields, Text1 and Text2 so you can see how the updated is being done when you run this example.


    @Label: <input type="text" style="margin: 5px;" @bind-value="@TextBoxValue" @oninput=OnInputCallBack /> 
    
    @code{
        public string? Label { get; set; }
        public string? TextBoxValue { get; set; }
    
        protected override Task OnInitializedAsync()
        {
            return base.OnInitializedAsync();
        }
    
        [Parameter]
        public EventCallback<ChangeEventArgs> OnInputCallBack { get; set; }
    }
    

    @page "/"
    
    @if (type != null)
    {
        <DynamicComponent Type="type" @ref="dc" Parameters="parameters" />
    }
    
    <button class="btn btn-primary" @onclick="SaveToDatabase">Submit</button>
    
    <h3>@Text1</h3>
    
    <h3>@Text2</h3>
    
    @code {
        Dictionary<string, object>? parameters;
        Type? type;
        DynamicComponent? dc;
        string? Text1;
        string? Text2;
    
        protected override void OnInitialized()
        {
            parameters = new() { { "OnInputCallBack", EventCallback.Factory.Create<ChangeEventArgs>(this, GetInput) } };
            type = typeof(TextBoxComponent);
        }
    
        private void GetInput(ChangeEventArgs e)
        {
            Text2 = (string?)e.Value;
        }
    
        private void SaveToDatabase()
        {
            Text1 = (dc?.Instance as TextBoxComponent)?.TextBoxValue;
        }
    }