Search code examples
textboxsubmitform-submitblazordynamic-forms

How to retrive data from dynamic text box using Blazor


MyCustomControl.razor

<input type="text" id="@id" />
@code {
     [Parameter]
    public string id { get; set; }
}

Test.Razor

@page "/test"

<button @onclick="@addCompoment">add text box</button>
<div class="simple-list-list">
    @if (componentListTest == null)
    {
        <p>You have no items in your list</p>
    }
    else
    {
        <ul>
            @foreach (var item in componentListTest)
            {
                @item<br/>
            }
        </ul>
    }
</div>

@functions {

    private List<RenderFragment> componentListTest { get; set; }
    private int currentCount { get; set; }
    private string TxtExample { get; set; }
    protected  void OnInit()
    {
        currentCount = 0;
        componentListTest = new List<RenderFragment>();
    }


    protected void addCompoment()
    {
        if(componentListTest==null)
        {
        componentListTest = new List<RenderFragment>();
        }
        componentListTest.Add(CreateDynamicComponent(currentCount));
        currentCount++;
    }


    RenderFragment CreateDynamicComponent(int counter) => builder =>
    {

        try
        {
            var seq = 0;
            builder.OpenComponent(seq, typeof(MyCustomControl));
            builder.AddAttribute(++seq, "id", "listed-" + counter);
            builder.CloseComponent();
        }
        catch (Exception ex)
        {

            throw;
        }


    };
}

After Adding the textbox dynamically,how to retrieve all input data from the textbox (after clicking on the submit button.) How to interact with dynamic component and fetch Value. MyCustomControl is component, Append in Test Razor Page. for these component create an attribute like bind-value to get input field data given by user


Solution

  • There are a couple of solutions to this type of issue, depending on the general design of your app, constraints, and such like. The following solution is simple. Generally speaking, it involves passing the value of the added text box to a parent component to be saved in a list object. The parent component has a button that displays the list of text when clicked.

    The following is the definition of the child component:

    MyCustomControl.razor

        <input type="text" @bind="@Value" id="@ID" />
    
        @code {
            private string _value;
    
            public string Value
            {
                get { return _value; }
    
                set
                {
                    if (_value != value)
                    {
                        _value = value;
                        if (SetValue.HasDelegate)
                        {
                            SetValue.InvokeAsync(value);
                        }
                     }
                 }
             }
    
            [Parameter]
            public string ID { get; set; }
            [Parameter]
            public EventCallback<string> SetValue { get; set; }
        } 
    

    Usage in a parent component

        <button @onclick="@addCompoment">add text box</button>
    
        <div class="simple-list-list">
            @if (componentListTest == null)
            {
                <p>You have no items in your list</p>
            }
            else
            {
                <ul>
                    @foreach (var item in componentListTest)
                    {
                        @item
                        <br />
                    }
                </ul>
            }
        </div>
    
        <p><button @onclick="@ShowValues">Show values</button></p>
    
        @if (Display)
        {
            <ul>
                @foreach (var value in values)
                {
                    <li>@value</li>
    
                }
            </ul>
        }
    
        @code {
    
            public void SetValue(string value)
            {
               values.Add(value);
            }
    
        private List<RenderFragment> componentListTest { get; set; }
        private List<string> values = new List<string>();
        private int currentCount { get; set; }
    
        protected override void OnInitialized()
        {
            currentCount = 0;
            componentListTest = new List<RenderFragment>();
        }
    
        private bool Display;
    
        private void ShowValues()
        {
            if (values.Any())
            {
                Display = true;
            }
        }
        protected void addCompoment()
        {
            if (componentListTest == null)
            {
                componentListTest = new List<RenderFragment>();
            }
            componentListTest.Add(CreateDynamicComponent(currentCount));
            currentCount++;
        }
    
    
        RenderFragment CreateDynamicComponent(int counter) => builder =>
        {
            try
            {
    
               builder.OpenComponent(0, typeof(MyCustomControl));
                builder.AddAttribute(1, "id", "listed-" + counter);
                builder.AddAttribute(2, "SetValue", Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<Microsoft.AspNetCore.Components.EventCallback<System.String>>(Microsoft.AspNetCore.Components.EventCallback.Factory.Create<System.String>(this, this.SetValue )));
                builder.CloseComponent();
                }
                catch (Exception ex)
                {
                    throw;
                }
            };
        }
    

    Note:

    1. Notice the SetValue attribute I've added to the CreateDynamicComponent's builder. This provides a Component Parameter to MyCustomControl of type EventCallback<string> which is assigned to the SetValue parameter property:
        [Parameter]
        public EventCallback<string> SetValue { get; set; } 
    

    And it is used (trigger the method which is also called SetValue in the parent component. You can change the name if you like) to pass the changed value from the child component to the parent component.

    1. Use code instead of functions.

    2. Note that I've made some modifications in your code: OnInitialized instead of OnInit (obsolete), sequence numbers should not created the way you do. Refer to this article written by Steve Sanderson ...

    Hope this helps...