0
votes

I have a wizard blazor component that contains a form. The wizard control consists of 2 Blazor components -

Wizard.razor

<CascadingValue Value="this">    
<div id="@Id">

    <div id="container-fluid">
        @ChildContent
    </div>
</div>
<button class="btn btn-primary btn-lg" type="button"
        disabled="@(ActiveStepIx == 0)" @onclick="GoBack">
    Previous
</button>
<button class="btn btn-primary btn-lg"
        type="@(IsLastStep ? "submit" : "button")" @onclick="GoNext">
    @(IsLastStep ? "Submit" : "Next")
</button>
</CascadingValue>

/// <summary>
/// Wizard Component
/// </summary>
public partial class Wizard
{
    /// <summary>
    /// List of <see cref="WizardStep"/> added to the Wizard
    /// </summary>
    protected internal List<WizardStep> Steps = new List<WizardStep>();

    /// <summary>
    /// The control Id
    /// </summary>
    [Parameter]
    public string Id { get; set; }

    /// <summary>
    /// The ChildContent container for <see cref="WizardStep"/>
    /// </summary>
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    /// <summary>
    /// The Active <see cref="WizardStep"/>
    /// </summary>
    [Parameter]
    public WizardStep ActiveStep { get; set; }

    /// <summary>
    /// The Index number of the <see cref="ActiveStep"/>
    /// </summary>
    [Parameter]
    public int ActiveStepIx { get; set; }

    /// <summary>
    /// Determines whether the Wizard is in the last step
    /// </summary>

    public bool IsLastStep { get; set; }

    /// <summary>
    /// Sets the <see cref="ActiveStep"/> to the previous Index
    /// </summary>

    protected internal void GoBack()
    {
        if (ActiveStepIx > 0)
            SetActive(Steps[ActiveStepIx - 1]);
    }

    /// <summary>
    /// Sets the <see cref="ActiveStep"/> to the next Index
    /// </summary>
    protected internal void GoNext()
    {
        if (ActiveStepIx < Steps.Count - 1)
        {
            SetActive(Steps[(Steps.IndexOf(ActiveStep) + 1)]);
        }                
        else
        {
            // TODO: SUBMIT THE FORM
            Console.WriteLine("FORM SUBMITTED");
        }                
    }

    /// <summary>
    /// Populates the <see cref="ActiveStep"/> the Sets the passed in <see cref="WizardStep"/> instance as the
    /// </summary>
    /// <param name="step">The WizardStep</param>

    protected internal void SetActive(WizardStep step)
    {
        ActiveStep = step ?? throw new ArgumentNullException(nameof(step));

        ActiveStepIx = StepsIndex(step);
        if (ActiveStepIx == Steps.Count - 1)
            IsLastStep = true;
        else
            IsLastStep = false;
    }

    /// <summary>
    /// Retrieves the index of the current <see cref="WizardStep"/> in the Step List
    /// </summary>
    /// <param name="step">The WizardStep</param>
    /// <returns></returns>
    public int StepsIndex(WizardStep step) => StepsIndexInternal(step);
    protected int StepsIndexInternal(WizardStep step)
    {
        if (step == null)
            throw new ArgumentNullException(nameof(step));

        return Steps.IndexOf(step);
    }
    /// <summary>
    /// Adds a <see cref="WizardStep"/> to the WizardSteps list
    /// </summary>
    /// <param name="step"></param>
    protected internal void AddStep(WizardStep step)
    {
        Steps.Add(step);
    }

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            SetActive(Steps[0]);
            StateHasChanged();
        }
    }
}

WizardStep.razor

@if (Parent.ActiveStep == this)
{
<div id="step-@(Parent.StepsIndex(this) + 1)">
    @ChildContent
</div>
}

/// <summary>
/// Wizard Step component
/// </summary>
public partial class WizardStep
{
    /// <summary>
    /// The <see cref="Wizard"/> container
    /// </summary>
    [CascadingParameter]
    protected internal Wizard Parent { get; set; }

    /// <summary>
    /// The Child Content of the current <see cref="WizardStep"/>
    /// </summary>
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    /// <summary>
    /// The Name of the step
    /// </summary>
    [Parameter]
    public string Name { get; set; }


    protected override void OnInitialized()
    {
        Parent.AddStep(this);
    }
}

The wizard contains a form. I am displaying this form in a Modal popup and on the parent page I have a method called HandleValidSubmit() which submits the form. How can I call this method from the Submit button on Wizard.razor?

ParentPage.razor

<EditForm Model="@ItemForTradeObject">
<Wizard Id="AddItemWizard">
    <WizardStep Name="Item">
        <div class="form-group  col-md-6">
        <label class="sr-only" for="itemName">Item Name</label>
        <div class="input-group">
        <InputText id="itemName" class="form-control" @bind-Value="@ItemForTradeObject.ItemName" />          <ValidationMessage For="@(() => ItemForTradeObject.ItemName)" />
    </div>
    </WizardStep>
    <WizardStep Name="Costing">
        <div class="form-group  col-md-6">
        <label class="sr-only" for="shippingCost">Cost Price</label>
        <div class="input-group">
            <div class="input-group-addon">£</div>
                <InputText id="costPrice" class="form-control" @bind-Value="@ItemForTradeObject.CostPrice" />
            </div>
            <ValidationMessage For="@(() => ItemForTradeObject.CostPrice)" />
        </div>
    </WizardStep>
</Wizard>

@code {
private async void HandleValidSubmit()
{
    if (ItemForTradeObject.Id == 0)
    {
        // Add
        ItemForTradeObject.UserId = await localStorage.GetItemAsync<string>("userid");

        await Http.PostJsonAsync("api/trading/add", ItemForTradeObject);
    }
    else
    {
        // Update
        ItemForTradeObject.UserId = await localStorage.GetItemAsync<string>("userid");

        await Http.PostJsonAsync("api/trading/update", ItemForTradeObject);
    }

    await CloseTaskModal();
    DataChanged?.Invoke();
}
}
1

1 Answers

1
votes

How can I call this method from the Submit button on Wizard.razor?

You don't call the HandleValidSubmit from the Submit button on Wizard.razor. It is automatically called when you hit the Submit button and the model is valid.

Do the following:

ParentPage.razor

<EditForm Model="@ItemForTradeObject" OnValidSubmit="HandleValidSubmit">
@*.............................................*@
</EditForm>

Wizard.razor

<button class="btn btn-success" type="submit">
    Submit Search
</button>

Hope this helps...