I have two independent components in a Blazor wasm app between whichi am trying to communicate. under certain cases the communication fails and I cannot understand why.
The(simplified) setup is as follows
<ParentComponent>
<HeaderComponent>
<ProgressBar IsLoading="<Set by IsLoading property from header>" />
</HeaderComponent>
<ResultContainer />
</ParentComponent>
The code behind looks something like this:
public class ResultContainerStateManager
{
public event Action OnLoadStart;
public event Action OnLoadFinish;
public NotifyLoadStart() => this.OnLoadStart?.Invoke();
public NotifyLoadFinish() => this.OnLoadFinish?.Invoke();
}
public partial class HeaderComponent
{
[Inject]
public ResultContainerStateManager ResultContainerStateManager { get; set; }
private bool IsLoading { get; set; }
protected override void OnInitialized()
{
this.ResultContainerStateManager.OnLoadStart += () => this.IsLoading = true;
this.ResultContainerStateManager.OnLoadFinish += () => this.IsLoading = false;
base.OnInitializer();
}
}
public partial class ResultContainer
{
[Inject]
public ResultContainerStateManager ResultContainerStateManager { get; set; }
private bool IsLoading { get; set; }
protected override async Task OnParametersSetAsync()
{
<code>
if (shouldLoadData)
{
this.ResultContainerStateManager.NotifyLoadStart();
<more code>
this.ResultContainerStateManager.NotifyLoadFinish();
}
await base.OnParametersSetAsync();
}
}
public partial class ProgressBar
{
[Parameter]
public bool IsLoading { get; set; }
}
Where the IsLoading parameter from the progress bar is set from the IsLoading property from HeaderComponent, like
<div id="headerComponent">
<More html here>
<ProgressBar IsLoading="@this.IsLoading" />
</div>
I don't think it matters, but the progress bar itself uses the MatProgress component, like so:
@if (this.IsLoading)
{
<MatProgress Indeterminate="true" />
}
else
{
<Other html code>
}
The problem is that the progress bar starts when the ResultContainer executes the NotifyLoadStart() method, but it doesn't stop when the NotifyLoadFinish() method is executed.
I can see when debugging that the IsLoading property of the HeaderComponent is set back to false after the NotifyLoadFinish() call, but it has no Effect on the UI.
What I have tried so far:
- injecting the
ResultContainerStateManagerdirectly into the Progress bar - I have tried changing the envents to Func and handling at all asynchronously
- I have tried adding
await Task.Yield()after eachNotifycall - I have tried adding
this.StateHasChanged()calls in the event handlers and after eachNotifycall (I know the latter should not change anything at all, since it is not in the same hierarchy)
None of that changed anything and I would really like to understand why.
The only success I've had was when using EventCallbacks instead of the events. But I am using events in lots of other places and they all seem to work fine.
Could somebody tell me why events seem to fail and how this can be fixed?
IsLoadingof theProgressBarcomponent is defined in what other component? What component "owns" it? Is itParentComponent,HeaderComponentor the page? - Just the bennoHeaderComponent. The header passes it's ownIsLoadingproperty into theProgressBar. i'll change the code to make that clearer. - yu_ominae