Как получить данные из динамического текстового поля с помощью 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;
        }


    };
}

После динамического добавления текстового поля, как получить все входные данные из текстового поля (после нажатия кнопки отправки). Как взаимодействовать с динамическим компонентом и получить значение. MyCustomControl - это компонент, добавляемый на страницу Test Razor. для этих компонентов создайте атрибут, например значение привязки, чтобы получить данные поля ввода, предоставленные пользователем


person user12428054    schedule 02.12.2019    source источник


Ответы (1)


Есть несколько решений этого типа проблемы, в зависимости от общего дизайна вашего приложения, ограничений и тому подобного. Следующее решение простое. Вообще говоря, он включает в себя передачу значения добавленного текстового поля родительскому компоненту для сохранения в объекте списка. У родительского компонента есть кнопка, при нажатии на которую отображается список текста.

Ниже приводится определение дочернего компонента:

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; }
    } 

Использование в родительском компоненте

    <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;
            }
        };
    }

Примечание:

  1. Обратите внимание на атрибут SetValue, который я добавил в конструктор CreateDynamicComponent. Это обеспечивает параметр компонента для MyCustomControl типа EventCallback<string>, который назначен свойству параметра SetValue:
    [Parameter]
    public EventCallback<string> SetValue { get; set; } 

И он используется (запускает метод, который также называется SetValue в родительском компоненте. Вы можете изменить имя, если хотите), чтобы передать измененное значение из дочернего компонента в родительский компонент.

  1. Используйте код вместо функций.

  2. Обратите внимание, что я внес некоторые изменения в ваш код: OnInitialized вместо OnInit (устаревший), порядковые номера не должны создаваться так, как вы. См. эту статью, написанную Стивом Сандерсоном ...

Надеюсь это поможет...

person enet    schedule 03.12.2019
comment
Назначение Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck ‹Microsoft.AspNetCore.Components.EventCallback‹ System.String ›› (Microsoft.AspNetCore.Components.EventCallback.Factory.Create ‹System.String›? Здесь я использую одно текстовое поле Итак, мы использовали строку. Если у нас есть класс модели. Что мы хотим сделать? - person user12428054; 04.12.2019
comment
TypeCheck фактически гарантирует, что фабрика EventCallback может создать соответствующий делегат со спецификатором типа, ссылкой на владельца события и методом обработки события. Это то, что я скопировал из кода, созданного компилятором, вам действительно не нужно знать это, чтобы программировать в Blazor, и, конечно, это можно упростить. - person enet; 04.12.2019
comment
Как я уже упоминал в своем ответе, решение вашей проблемы можно найти несколькими способами. Однако я не могу ответить на ваш вопрос конкретно, поскольку ваш вопрос (в общем выше) не конкретен. В любом случае вы можете создать службу, которая хранит модель или список моделей, и внедрить эту службу в родительский и дочерний компоненты, чтобы каждый раз, когда дочерний компонент создает новую модель (а не просто строку), родительский компонент сможет получить доступ к только что добавленному экземпляру модели. - person enet; 04.12.2019
comment
Еще одно жизнеспособное решение: определить модель или список объектов модели в родительском компоненте (вместо списка строк, как в текущем решении), зафиксировать ссылку на родительский компонент и передать ее дочернему компоненту. Вы можете передать это дочерним компонентам, чтобы они имели прямой доступ к списку объектов модели ... - person enet; 04.12.2019
comment
В моем случае мне нужно добавить одно текстовое поле и одно поле выбора, когда я нажимаю кнопку «Добавить», и мне нужно получить значения при нажатии на «Отправить». - person user12428054; 05.12.2019