dhrm
dhrm

Reputation: 14944

Blazor - update state in URL

I'm trying to create a Blazor webassambly page where about 8 filter states are stored and synchronised as query parameters.

Currently, the below sample page supports that when I request /orders?status=uploading the status is preset with Uploading and when I choose another value in the InputSelect the state is updated on the Status property on the model.

But further, when choosing another value in the InputSelect, I would like the URL to update to reflect that (without reloading the page).

How is best practices for updating the URL to always reflect the state of the page (with multiple parameters)?

@page "/orders"

<PageTitle>Navigation demo</PageTitle>

<EditForm Model="_model">
    <InputSelect @bind-Value="_model.Status">
        @foreach (var orderStatus in Enum.GetValues(typeof(OrderStatus)))
        {
            <option value="@orderStatus">@orderStatus</option>
        }
    </InputSelect>
</EditForm>

Selected status: @_model.Status

@code {

    public enum OrderStatus
    {
        Created,
        Uploading,
        Uploaded
    }

    readonly Model _model = new();

    class Model
    {
        public OrderStatus Status { get; set; }
    }

    [Parameter]
    [SupplyParameterFromQuery(Name = "status")]
    public string? StatusString
    {
        get => _model.Status.ToString();
        set
        {
            var couldParse = Enum.TryParse(value, true, out OrderStatus newStatus);
            if (couldParse)
            {
                _model.Status = newStatus;
            }
        }
    }

}

Upvotes: 1

Views: 2055

Answers (2)

Szhlopp
Szhlopp

Reputation: 51

Just leaving this here for the next person looking for this, as of .NET 6, you're able to use an override to update/replace URI parameters easily.

Make sure you inject a NavigationManager

@inject NavigationManager nav

Now anywhere else in your code:

//Update the id query param with a new value. Super easy!
nav.NavigateTo(nav.GetUriWithQueryParameter("id", NewID), false, true);

There's also a GetUriWithQueryParameters for multiple values.

Upvotes: 3

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30177

Here's some demo code that demonstrates how to update the Url. Note the code comments on what get's hit when. On navigating to the same route, only OnParametersSet{Async} gets hit.

@page "/"
@inject NavigationManager NavManager

<PageTitle>Index</PageTitle>

<select class="form-select" @bind=this._model.Status >
    <option value="Created">Created</option>
    <option value="Uploading">Uploading</option>
    <option value="Uploaded">Uploaded</option>
</select>
<button class="btn btn-dark" @onclick=SetStatus>Select</button>

@code {
    private string status = string.Empty; 

    public enum OrderStatus
    {
        Created,
        Uploading,
        Uploaded
    }

    readonly Model _model = new();

    class Model
    {
        public OrderStatus Status { get; set; }
    }

    [Parameter]
    [SupplyParameterFromQuery(Name = "status")]
    public string? StatusString { get; set; }

    protected override void OnInitialized()
    {
        // I'm only hit on first load
        base.OnInitialized();
    }

    protected override void OnParametersSet()
    {
        // I'm hit every time
        base.OnParametersSet();
    }

    private void SetStatus()
    {
        NavManager.NavigateTo($"/?status={this._model.Status}");
    }
}

Upvotes: 4

Related Questions