Blazor (Razor Components) Обновить дочерний компонент из родительского компонента
У меня есть простой дочерний компонент Blazor (MyModal), например:
<div class="modal">
<h3>@Title</h3>
@BodyTemplate
</div>
@code
{
[Parameter] string Title { get; set; }
[Parameter] RenderFragment BodyTemplate { get; set; }
}
В моем родительском компоненте я называю это так:
<MyModal Title="Super Cool Modal">
<BodyTemplate>
@MyObject.Name
</BodyTemplate>
</MyModal>
public MyObject MyObject { get; set; } = new MyObject();
Позже, после того, как страница изначально отрендерена, я обновляю MyObject
но сам дочерний компонент ссылается @MyObject.Name
никогда не обновляет
Кажется, я должен принудительно обновить дочерний объект после того, как я обновил объект (StateHasChanged
) но не уверен, как это сделать с этим примером.
6 ответов
Вы можете попробовать это
Ребенок
Создайте общедоступный метод обновления, который вы можете вызывать из родительского
<div class="modal">
<h3>@Title</h3>
@BodyTemplate
</div>
@code
{
[Parameter] string Title { get; set; }
[Parameter] RenderFragment BodyTemplate { get; set; }
public void RefreshMe()
{
StateHasChanged();
}
}
Родитель
Вызов дочернего метода обновления
<MyModal Title="Super Cool Modal"
@ref="ChildComponent">
<BodyTemplate>
@MyObject.Name
</BodyTemplate>
</MyModal>
@code
{
public MyObject MyObject { get; set; } = new MyObject();
protected UploadDownloadComponent ChildComponent;
//Call this method to update the child
private void Change(TreeEventArgs args)
{
ChildComponent.RefreshMe();
}
}
Вы можете просто использовать CascadingParameter.
В родительском компоненте просто вызовите дочерний компонент следующим образом:
<CascadingValue Value="selectedChats[0].Id" Name="chatID">
<AdminChatComponent> </AdminChatComponent>
</CascadingValue>
Дочерний компонент:
[CascadingParameter(Name ="chatID")]
public string chatID { get; set; }
После этого все, что вам нужно сделать, это просто создать метод OnParametersSetAsync в дочернем компоненте и просто привязать свое значение к родительскому компоненту. В моем случае я привязал свое значение к выбору строки datagrid.
После этого всякий раз, когда привязанное значение изменяется в родительском компоненте, ваш дочерний компонент также запускает метод OnParametersSetAsync.
Поскольку <MyModal>
имеет RenderFragment
параметр достаточно позвонить StateHasChanged()
в родительском компоненте он пересчитает и отобразит все дочерние компоненты с параметрами из родительского.
Вы можете выполнить «OnParametersSetAsync()» для дочернего компонента:
Родительский компонент:<childCompoment param="@paramParent" />
Дочерний компонент:
[Параметр]public string param{get;set;}
защищенное переопределение асинхронной задачи OnInitializedAsync() {await Refresh ();}
асинхронное обновление задачи (){}
Примечание: ваш шаблонный компонент был сделан неправильно, а также то, как вы его используете. Пожалуйста, запустите предоставленный мною код, убедитесь, что он работает, и просмотрите внесенные мной изменения. Если у вас есть вопросы, не стесняйтесь спрашивать.
Ваш код должен выглядеть примерно так:
MyModal
<div class="modal">
<h3>@Title</h3>
@BodyTemplate (MyObject)
</div>
@code
{
[Parameter] string Title { get; set; }
[Parameter] RenderFragment BodyTemplate { get; set; }
[Parameter] MyObject MyObject{ get; set; }
}
использование
<MyModal Title="Super Cool Modal" MyObject="@MyObject">
<BodyTemplate>
@context.Name
</BodyTemplate>
</MyModal>
public MyObject MyObject { get; set; } = new MyObject();
Надеюсь это поможет...
У меня есть другой пример со сложным объектом параметра, который необходимо сериализовать в модель формы.
OnParametersSetAsync() обновит дочерний компонент при изменении параметра.
Нам нужно привязать дочерний параметр с помощью @ bind-Job="_job"
Родитель:
<div class="tab-pane active" id="kt_job_tab_1">
<JobEdit @bind-Job="_job"></JobEdit>
</div>
@code
{
private Job _job;
protected override async Task OnInitializedAsync()
{
_job = await GetJob();
await base.OnInitializedAsync();
}
}
Ребенок:
<EditForm Model="@_model" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<div class="form-group row">
<label class="col-xl-3 col-lg-3 col-form-label text-sm-left text-lg-right">Title</label>
<div class="col-lg-9 col-xl-6">
<InputText @bind-Value="_model.JobTitle" class="form-control form-control-solid form-control-lg" />
</div>
</div>
<div class="form-group row">
<label class="col-xl-3 col-lg-3 col-form-label text-sm-left text-lg-right">Department</label>
<div class="col-lg-9 col-xl-6">
<InputText @bind-Value="_model.Department" class="form-control form-control-solid form-control-lg" />
</div>
</div>
</EditForm>
@code {
[Parameter]
public Job Job { get; set; }
[Parameter]
public EventCallback<Job> JobChanged { get; set; }
private Model _model;
protected override async Task OnInitializedAsync()
{
InitializeModel();
await base.OnInitializedAsync();
}
//THIS WILL UPDATE MODEL IF PARENT CHANGES
protected override async Task OnParametersSetAsync()
{
InitializeModel();
await base.OnParametersSetAsync();
}
private async void HandleValidSubmit()
{
//WE CODE HERE
//THEN
//THIS UPDATES PARENT IF CHILD JOB CHANGES
await JobChanged.InvokeAsync(Job);
StateHasChanged();
}
private void InitializeModel()
{
_model = new Model
{
JobIdentifier = Job.Identifier,
JobTitle = Job.JobTitle,
Department = Job.Department
};
}
private class Model
{
[Required]
public string JobIdentifier { get; set; }
[Required]
public string JobTitle { get; set; }
[Required]
public string Department { get; set; }
}
}