Reputation: 1566
Parent:
<TourOfficesSettings @ref="SettingsModal" @bind-Informations="informations"></TourOfficesSettings>
<button class="btn btn-outline-primary" type="button" @onclick="() => SettingsModal.Modal.Open()"><span>Settings</span></button>
@code {
public List<TouOffInformationModel> informations { get; set; }
private TourOfficesSettings SettingsModal { get; set; }
protected override async Task OnInitializedAsync()
{
try
{
var result = await Http.GetFromJsonAsync<List<TouOffInformationModel>>("api/TourOffices");
informations = result.ToList();
filteredTouOffDatas = touOffDatas;
}
catch (AccessTokenNotAvailableException exception)
{
exception.Redirect();
}
}
}
Child:
<Modal @ref="Modal" ModalSize="xl" ModalId="settings">
<TouOffInfoForm @ref="informationModal" @bind-Informations="Informations"></TouOffInfoForm>
</Modal>
@code {
[Parameter]
public List<TouOffInformationModel> Informations { get; set; }
[Parameter]
public EventCallback<List<TouOffInformationModel>> InformationsChanged { get; set; }
public Modal Modal { get; set; }
private TouOffInfoForm informationModal { get; set; }
}
nested child:
<button class="btn btn-outline-danger" @onclick="Create()">Create</button>
@code {
[Parameter]
public List<TouOffInformationModel> Informations { get; set; }
[Parameter]
public EventCallback<List<TouOffInformationModel>> InformationsChanged { get; set; }
public async Task Create() {
var model = new TouOffInformationModel(....);
Informations.Add(model);
await InformationsChanged.InvokeAsync(Informations);
}
}
My problem is: Only "nested child" changes "Informations", after changed I see changes in "Child" but in "parent" they only happen if I open "Child" again and close it.
Can you guys help me set "Child" so I can do there "InformationsChanged.InvokeAsync()" once the Information is changed?
Upvotes: 0
Views: 534
Reputation: 3063
This appears to be a "value vs. reference" issue. You are changing the underlying data in the list item itself, but remember that the list is a reference item in memory and you have to treat it as such. StateHasChanged
has a context of the component it's called on and any child components, meaning Blazor will behave as expected within the bounds of one component, but you have to notify the higher level components of the change as well.
The simple fix from my perspective (and also a way to clean the code up a bit) is to keep the list and all of it's state management logic in the same component. That would mean your top level "Parent" component should have the Create(TouOffInformationModel)
method (note method signature!), since that is where the list Informations
is defined. Then you can pass the Create(TouOffInformationModel)
method down the component tree as an event callback, and when the child component invokes it, it's actually happening at the top of the tree. If there are still data display issues you can include StateHasChanged()
in the new Create method and it should all work. That would make your "Parent" component code block look something like this:
@code {
public List<TouOffInformationModel> informations { get; set; }
private TourOfficesSettings SettingsModal { get; set; }
public Task Create(TouOffInformationModel model) {
informations.Add(model);
// This may not be needed, but try it both ways
StateHasChanged();
}
protected override async Task OnInitializedAsync()
{
try
{
var result = await Http.GetFromJsonAsync<List<TouOffInformationModel>>("api/TourOffices");
informations = result.ToList();
filteredTouOffDatas = touOffDatas;
}
catch (AccessTokenNotAvailableException exception)
{
exception.Redirect();
}
}
}
Then pass that Create
method down to wherever it's needed.
A second, more robust option is to implement an injected service and / or build a data model that will handle it's own state management and notify as needed, but that is a larger and more complex scope than what you are asking about here. Still, you would gain a great deal of decoupling by doing so and I recommend you research state management options for Blazor if you are interested.
Upvotes: 1