Get Child Component binded values in Parent Component in Blazor
BLAZOR WAY:
To do this they way it is intended to be done in Blazor, start by using a Blazor component. The example below uses the component SingleSelect.razor which is a simplified HTML Select element.
The component is referenced by a tag that is automatically generated by VisualStudio from the name of the razor component file so in this case the tag will be <SingleSelect>
.
In order to get a value from the child component, a reference variable that points to the child component is created by the parent.
This is done by creating a local variable of the child in the parent:
private SingleSelect singleSelect;
and then linking it in the child tag:
<SingleSelect @ref="singleSelect" Options="SingleSelectOptions"></SingleSelect>
This allows reference to the child data by utlizing the reference variable:
singleSelect.SelectedOption.Value
The following pages give a full example.
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 singleSelectResult;
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; }
}
}
You should do the following:
- Define an EventCallback delegate property in your Child Component:
[Parameter] protected EventCallback<string> OnUserNameChanged { get; set; }
This property will contain a delegate to a method defined on the Parent Component.
- Define a property and a backing variable in your Child Component:
private string username;
public string UserName
{
get => username;
set
{
username = value;
// Invoke the delegate passing it the changed value
OnUserNameChanged?.Invoke(value);
}
}
- Define a method in your Parent Component that gets called from the Child Component when the user name is changed:
public async void UserNameChanged(string username)
{
// Gets and consume the user name
}
- This is how your Child Component is used in your Parent Component: Note that we assign the method name to the attribute OnUserNameChanged, which is the delegate property in your Child Component
<cinput OnUserNameChanged="UserNameChanged" ></cinput>
<input type="text" bind="@email">
<input type="button" onclick="@onsubmit">
Hope this helps...
This is what Steve Anderson has to say about ref:
Use case
The intended use case is to allow parent components to issue commands to child components such as "show" or "reset".
Even then, architecturally it's a compromise because it would be cleaner still for your child components to be stateless (that is, not acting on any state other than their parameters) and in that case it's not even theoretically possible for it to make sense to issue an "action" other than by changing their child's parameters, in which case you don't need ref at all.
It is strongly not recommended that you use ref as a way of mutating the state of child components. Instead, always use normal declarative parameters to pass data to child components. This will cause child components to re-render at the correct times automatically. We are moving towards changing how parameters on components are represented so that by default they are encapsulated and not possible to read/write from outside.