Reputation: 20179
I have a simple child Blazor component (MyModal) like so:
<div class="modal">
<h3>@Title</h3>
@BodyTemplate
</div>
@code
{
[Parameter] string Title { get; set; }
[Parameter] RenderFragment BodyTemplate { get; set; }
}
In my Parent component I'm calling it like so:
<MyModal Title="Super Cool Modal">
<BodyTemplate>
@MyObject.Name
</BodyTemplate>
</MyModal>
public MyObject MyObject { get; set; } = new MyObject();
Later on after the page has initially rendered I update MyObject
but the Child component itself referencing @MyObject.Name
never updates.
Seems I have to force refresh on the child object after I've updated the Object (StateHasChanged
) but not sure how to do this with this example.
Upvotes: 22
Views: 33171
Reputation: 368
You can just use CascadingParameter.
In your parent component, just call child component like this:
<CascadingValue Value="selectedChats[0].Id" Name="chatID">
<AdminChatComponent> </AdminChatComponent>
</CascadingValue>
Child Component:
[CascadingParameter(Name ="chatID")]
public string chatID { get; set; }
After that, all you need to do is just make a OnParametersSetAsync method in child component andjust bind your value in parent component. In my case I binded my value to datagrid row select.
After that whenever binded value changes on parent component, also your child component will trigger OnParametersSetAsync method.
Upvotes: 8
Reputation: 1133
I got a different example with a complex parameter object that has to be serialized to a form model.
OnParametersSetAsync() will update child component if parameter changes.
We need to bind child parameter using @bind-Job="_job"
Parent:
<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();
}
}
Child:
<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; }
}
}
Upvotes: -1
Reputation: 151
You can do "OnParametersSetAsync()
" on child component:
Parent component:
<childCompoment param="@paramParent" />
Child component:
[Parameter]
public string param{get;set;}
protected override async Task OnInitializedAsync(){await Refresh();}
async Task Refresh(){}
Upvotes: -1
Reputation: 18511
Since <MyModal>
has a RenderFragment
parameter it's enough to call StateHasChanged()
on the parent component, it will recalculate and render all child components with parameters from the parent.
Upvotes: 1
Reputation: 1356
You can try this
Child
Create a public refresh method that you can call from parent
<div class="modal">
<h3>@Title</h3>
@BodyTemplate
</div>
@code
{
[Parameter] string Title { get; set; }
[Parameter] RenderFragment BodyTemplate { get; set; }
public void RefreshMe()
{
StateHasChanged();
}
}
Parent
Call child refresh method
<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();
}
}
Upvotes: 28