Получение значений, привязанных к дочернему компоненту, в родительском компоненте в Blazor

#c# #blazor

#c# #blazor

Вопрос:

Допустим, дочерний компонент с именем cinput.cshtml является

 <input type="text" bind="@username">

@functions{
string username;
}
  

и родительский компонент называется pform.cshtml

 <cinput></cinput>
<input type="text" bind="@email">
<input type="button" onclick="@onsubmit">

@functions{

string email;

public void onsubmit(){
   //Call api
}
}
  

итак, вопрос в том, как получить значение имени пользователя в родительском компоненте?

Ответ №1:

Вы должны выполнить следующее:

  1. Определите свойство делегата EventCallback в вашем дочернем компоненте:
 [Parameter] protected  EventCallback<string>  OnUserNameChanged { get; set; }
  

Это свойство будет содержать делегат метода, определенного в родительском компоненте.

  1. Определите свойство и вспомогательную переменную в вашем дочернем компоненте:
     private string username;
    public string UserName
    {
        get => username;
        set
        {
            username = value;
            // Invoke the delegate passing it the changed value
            OnUserNameChanged?.Invoke(value);
        }
    } 
  
  1. Определите метод в вашем родительском компоненте, который вызывается из дочернего компонента при изменении имени пользователя:
     public async void UserNameChanged(string username)
       {
          // Gets and consume the user name
       }
  
  1. Вот как ваш дочерний компонент используется в вашем родительском компоненте:
    Обратите внимание, что мы присваиваем имя метода атрибуту OnUserNameChanged, который является свойством делегирования в вашем дочернем компоненте
      <cinput OnUserNameChanged="UserNameChanged" ></cinput>
        <input type="text" bind="@email">
        <input type="button" onclick="@onsubmit">
  

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

Это то, что Стив Андерсон должен сказать о ссылке:

Пример использования

Предполагаемый вариант использования — разрешить родительским компонентам выдавать команды дочерним компонентам, таким как «показать» или «сбросить».

Даже в этом случае с архитектурной точки зрения это компромисс, потому что для ваших дочерних компонентов было бы еще чище оставаться без состояния (то есть не действовать ни на какое состояние, кроме их параметров), и в этом случае даже теоретически невозможно, чтобы имело смысл выдавать «действие», отличное от измененияих дочерние параметры, и в этом случае вам вообще не нужна ссылка.

Настоятельно не рекомендуется использовать ref как способ изменения состояния дочерних компонентов. Вместо этого всегда используйте обычные декларативные параметры для передачи данных дочерним компонентам. Это приведет к автоматическому повторному отображению дочерних компонентов в нужное время. Мы движемся к изменению представления параметров компонентов таким образом, чтобы по умолчанию они были инкапсулированы и не могли быть прочитаны / записаны извне.

Комментарии:

1. Это довольно много накладных расходов на одно свойство. И обновления в реальном времени не требуются (есть кнопка отправки). Мне нужно было бы увидеть это в более крупном примере композиции, как это работает.

2. Это способ кодирования SPA в Blazor (и Angular). Очень легко имитировать Стива Андерсона… Во фрагменте кода нет кнопки отправки или какого-либо подразумеваемого намерения ее использовать. нет элемента формы, который позволяет отправлять данные, и, помните, это веб-приложение SPA, которое взаимодействует с серверной частью через Ajax. Вы не публикуете традиционный способ… Добрый день.

3. Простой доступ к значениям намного проще ref . я не вижу смысла.

4. @ Syed Mohammed SMJ, смотрите Мой ответ в последней части моего ответа выше…

5. Работает ли это решение, если я хочу использовать несколько экземпляров дочернего элемента в одной и той же форме

Ответ №2:

СПОСОБ BLAZOR:

Чтобы сделать это так, как это должно быть сделано в Blazor, начните с использования компонента Blazor. В приведенном ниже примере используется компонент SingleSelect.razor, который является упрощенным элементом выбора HTML.

На компонент ссылается тег, который автоматически генерируется VisualStudio из имени файла компонента razor, поэтому в этом случае тег будет <SingleSelect> .

Для получения значения из дочернего компонента родительская переменная, указывающая на дочерний компонент, создается родительской переменной.

Это делается путем создания локальной переменной дочернего компонента в родительском компоненте:

private SingleSelect singleSelect;

а затем связать его с дочерним тегом:

<SingleSelect @ref="singleSelect" Options="SingleSelectOptions"></SingleSelect>

Это позволяет ссылаться на дочерние данные, используя ссылочную переменную:

singleSelect.SelectedOption.Value

На следующих страницах приведен полный пример.

Index.razor page

 @page "/"

<h3>Single Select Example</h3>
<h5 class="mt-2">Make your selection</h5>
<SingleSelect @ref="singleSelect" Options="SingleSelectOptions"></SingleSelect>
<button class="btn btn-primary mt-2" @onclick="SubmitSingleSelect">Submit</button>

<h5 class="mt-2">The following was selected:</h5>
<p>@singleSelectResult</p>

@code
{
    public partial class Index
    {
       
        SingleSelect singleSelect;
        string singleSelectResu<
        List<SingleSelectOption> SingleSelectOptions = new List<SingleSelectOption>
        {
            new SingleSelectOption{ Id=1, Value="One"},
            new SingleSelectOption{ Id=2, Value="Two"},
            new SingleSelectOption{ Id=3, Value="Three"},
            new SingleSelectOption{ Id=4, Value="Four"},
            new SingleSelectOption{ Id=5, Value="Five"},
            new SingleSelectOption{ Id=6, Value="Six"},
            new SingleSelectOption{ Id=7, Value="Seven"},
            new SingleSelectOption{ Id=8, Value="Eight"},
            new SingleSelectOption{ Id=9, Value="Nine"},
            new SingleSelectOption{ Id=10, Value="Ten"},
            new SingleSelectOption{ Id=11, Value="Eleven"},
        };


        private void SubmitSingleSelect()
        {
            singleSelectResult = singleSelect.SelectedOption.Value;
        }

    }
}

  

SingleSelect.razor page

 <div class="container">
    <div class="row">
        <div class="col-3">
            <select id="NotSelected" class="border" multiple="multiple" size="@boxSize" style="width: 200px">
                @foreach (var option in Options)
                {
                    <option id="@option.Id" @onclick="@(() => Select(option))">@option.Value</option>
                }
            </select>
        </div>
    </div>
</div>

@code 
{
    [Parameter]
    public List<SingleSelectOption> Options { get; set; } = new List<SingleSelectOption>();
    public SingleSelectOption SelectedOption { get; set; } = new SingleSelectOption { Id = 0, Value = " "};

    private int boxSize = 5;

    private void Select(SingleSelectOption option)
    {
        SelectedOption = option;
    }

    public class SingleSelectOption
    {
        public int Id { get; set; }
        public string Value { get; set; }
    }
}
  

Ответ №3:

Итак, я сделал что-то вроде этого

cinput.cshtml

 <input type="text" bind="@username">

@functions{
string username;

string getUsername(){
 return username;
}

}
  

в pform.cshtml

 <cinput ref="_cinput"></cinput>
<input type="text" bind="@email">
<input type="button" onclick="@onsubmit">

@functions{

string email;
Cinput _cinput

public void onsubmit(){
   //get username
   string uname = _cinput.getUsername();
   //Call api

}
}
  

https://learn.microsoft.com/en-us/aspnet/core/razor-components/components?view=aspnetcore-3.0#capture-references-to-components

Комментарии:

1. это сработало для меня просто отлично и даже получает привязанные значения

2. Это работает нормально, но только пока… В будущих версиях Blazor это звучит так, как будто сверху может не работать. Похоже, разработчики, работающие над Blazor, заранее сообщают нам, что использование Ref — плохой способ для подобных вещей. Жаль, что этот подход проще.

3. я просто надеюсь, что новый способ проще, как это.

4. Привет, люди, у вас есть какие-нибудь новости по этому поводу? Потому что это слишком просто для получения входных значений.

5. К вашему сведению, .NET 6.0 уже здесь, и ссылка все еще актуальна