I need help with dynamically building/generating multistep component with rendertreebuilder.
I have a two components: MultistepComponent (parent) and MultiStepNavigation (child). I also have a component builder class to build these components.
Rendering components does not work, I get an error:
Object reference not set to an instance of an object.That is because the MultiStepComponent property in MultiStepNavigation is empty. Using a component in razor page does not give this error.
I will be posting a lot of code, but you don't have to read every detail. I just want to give all the information.
MultiStepComponent.razor
<CascadingValue Value="this"><div id="@Id"><ul class="nav nav-pills nav-justified"> @foreach (var step in Steps) {<li id="step-@(StepsIndex(step) + 1)" class="nav-item"><a class="nav-link @((ActiveStep == step) ? "active" : "")" href="javascript: void(0)" @onclick="@(e=> SetActive(step))">@step.Name</a></li> }</ul><div id="container-fluid"><div class="navigatingBtns"><button class="btn btn-primary btn-lg" type="button" disabled="@(ActiveStepIndex == 0)" @onclick="GoBack"> Previous</button><button class="btn btn-primary btn-lg" type="@(IsLastStep ? "submit" : "button")" @onclick="GoNext"> @(IsLastStep ? "Submit" : "Next")</button></div> @ChildContent</div></div></CascadingValue>MultiStepComponent.razor.cs
public partial class MultiStepComponent { protected internal List<MultiStepNavigation> Steps = new List<MultiStepNavigation>(); [Parameter] public string Id { get; set; } [Parameter] public RenderFragment? ChildContent { get; set; } [Parameter] public MultiStepNavigation? ActiveStep { get; set; } [Parameter] public int ActiveStepIndex { get; set; } public bool IsLastStep { get; set; } protected internal void GoBack() { if (ActiveStepIndex > 0) { SetActive(Steps[ActiveStepIndex - 1]); } } protected internal void GoNext() { if (ActiveStepIndex < Steps.Count - 1) { SetActive(Steps[(Steps.IndexOf(ActiveStep) + 1)]); } } protected internal void SetActive(MultiStepNavigation step) { ActiveStepIndex = StepsIndex(step); if (ActiveStepIndex == Steps.Count - 1) { IsLastStep = true; } else { IsLastStep = false; } } public int StepsIndex(MultiStepNavigation step) => StepsIndexInternal(step); protected int StepsIndexInternal(MultiStepNavigation step) { return Steps.IndexOf(step); } protected internal void AddStep(MultiStepNavigation step) { Steps.Add(step); } protected override void OnAfterRender(bool firstRender) { if (firstRender) { SetActive(Steps[0]); StateHasChanged(); } } }MultiStepNavigation.razor
@if (MultiStepComponent.ActiveStep == this) { <div id="step-@(MultiStepComponent.StepsIndex(this) + 1)"> @ChildContent</div>}MultiStepNavigation.razor.cs
public partial class MultiStepNavigation { [CascadingParameter] protected internal MultiStepComponent MultiStepComponent { get; set; } [Parameter] public RenderFragment ChildContent { get; set; } = default!; [Parameter] public string Name { get; set; } = ""; protected override void OnInitialized() { if(MultiStepComponent != null) { MultiStepComponent.AddStep(this); } } }code to build componnts:
renderFragment = b => { b.OpenComponent<MultiStepComponent>(0); b.AddAttribute(1, "id", "MultiStepContainer"); b.OpenComponent<MultiStepNavigation>(2); b.AddAttribute(3, "Name", "First Step"); b.CloseComponent(); b.CloseComponent(); };Making a component on razor page myself does not give an error. It looks like this:
<MultiStepComponent Id="MultiStepContainer"><MultiStepNavigation Name="First Step"></MultiStepNavigation> </MultiStepComponent>What did I do wrong??