Search code examples
blazorblazor-webassembly

Set EditContext asynchronously in Blazor


I have a page, that loads a model in OnParametersSet. This model can be edited in a form. This works perfectly when I provide the model to EditForm directly via Model="ViewModel.Something". However I cannot make it work using EditContext, because EditContext wants to be initialized in OnParametersSet.

Unhandled exception rendering component: EditForm requires either a Model parameter, or an EditContext parameter, please provide one of these.
System.InvalidOperationException: EditForm requires either a Model parameter, or an EditContext parameter, please provide one of these.
   at Microsoft.AspNetCore.Components.Forms.EditForm.OnParametersSet()
   at Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()

Code:

@inject SomeViewModel ViewModel

@if(ViewModel.Something != null)
{
    <EditForm EditContext="editContext" OnValidSubmit="@Submit">
        // ...
    </EditForm>
}

@code
{
    [Parameter] public string? SomethingId { get; set; } = String.Empty;

    private EditContext editContext { get; set; } = default!;

    protected override void OnInitialized()
    {
        base.OnInitialized();

        ViewModel.PropertyChanged += (o, e) => StateHasChanged();

        ViewModel.LoadSomething.Subscribe(_ => editContext = new(ViewModel!.Something));
    }

    protected override void OnParametersSet()
    {
        base.OnParametersSet();

        if(!string.IsNullOrEmpty(SomethingId))
        {
            ViewModel.Query = new LoadSomethingQuery(SomethingId);
        }
    }

    //...
}

I want to make use of EditContext's IsModified property. Therefore I need to use EditContext instead of Model. But it does not work if EditContext is initialized after page initialization. Any idea how to solve this?


Solution

    • One option would be to check editContext for nulls:

      @if(editContext != null)
      {
          <EditForm EditContext="editContext" OnValidSubmit="@Submit">
              // ...
          </EditForm>
      }
      
    • Another option - Create the EditContext in ctor or OnInitialized and replace it with fresh instance in OnParametesSet:

      protected override void OnInitialized()
      {
          base.OnInitialized();
          editContext = new EditContext(...);
          ...
      }
      
      protected override void OnParametersSet()
      {
          base.OnParametersSet();
      
          if(!string.IsNullOrEmpty(SomethingId))
          {
              ViewModel.Query = new LoadSomethingQuery(SomethingId);
              ...
              editContext = new EditContext(...);
          }
      }