Aspnetcore.docs: Use OnParametersSet instead of OnIntialized to set Parameter default value

Created on 16 Nov 2020  ·  11Comments  ·  Source: dotnet/AspNetCore.Docs

The correct place to set a default Parameter values is in OnParametersSet, not OnInitialized.

OnInitalized does not always run after parameters are set, so in those scenarios, the default will not be set, resulting in a null parameter. OnParametersSet, however, always runs after parameters are set.

This sample shows the issue. Uncomment OnParametersSet and it will work correctly.

@page "/{text?}"

<h1>Blazor is @Text!</h1>
Click the following links:
<ul>
<li><a href="cool">Navigate to /cool</a></li>
<li><a href="awesome">Navigate to /awesome</a></li>
<li><a href="/">Navigate to /</a>  Default Value is not set from this link when using OnInitialized. Does work if OnParametersSet is used instead.</li>
</ul>

@code{
    [Parameter]
    public string Text { get; set; } = "fantastic";

    protected override void OnInitialized()
    {
        Text = Text ?? "fantastic";
    }

    //protected override void OnParametersSet()
    //{
    //    Text = Text ?? "fantastic";
    //}
}

Suggest:

Changing the sample to use OnParametersSet method instead of OnInitialized for setting Parameter default value.


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

Blazor P1 Source - Docs.ms

All 11 comments

Ah ... I think that was a cut and paste error this weekend. I was (as usual) going _VERY_ (too) _FAST_. 🏃

I'll patch that right now before anyone sees it. Nobody will ever know. 😉 lol

Hold on a sec @gregoryagu ... I read that exactly backwards.

It doesn't work? Are you sure? We always documented this (i.e., 3.x) as OnInitialized, and when I ran my local test it worked that way.

I'll check again locally shortly. I'm completely buried in WASM security at the moment. 😨

RE-POST ... My head is out of WASM security, so I tested a bit more.

@gregoryagu ... I can't repro what you're saying here for a non-index/non-default (landing) page. We always documented this for OnInitialized, since the inception of Blazor IIRC. I don't think it was ever considered that it doesn't run for the index (landing) page. I checked both of the 5.x common sample apps (WASM and Server). Ping @captainsafia on ...

does not always run after parameters are set, so in those scenarios, the default will not be set, resulting in a null parameter. OnParametersSet, however, always runs after parameters are set.

Default Value is not set from this link ...

"this link" refers to ...

<a href="/">Navigate to /</a> 

... when using OnInitialized. Does work if OnParametersSet is used instead.

When not using the app's index (landing) page, it works ...

With a param ...

Capture

Without a param ... (btw - this also works if reaching the page from Index.razor with <a href="/RouteParameter">Navigate to /RouteParameter</a>) ...

Capture1

@captainsafia ... If we do need to make a change, please clarify it for 3.x vs. 5.0, too, as we'll need to keep the non-optional-parameter coverage until 3.1 reaches EOL ...

https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-3.1#route-parameters

I'm thinking of the possibility that we would keep the OnInitialized coverage for 3.x because it _was_ the correct choice for that version but go with OnParametersSet for >=5.0, if OnParametersSet is the right thing to show.

More ...

I don't think that that's a viable test @gregoryagu. If you set an optional param on the index (landing) page of the app, the Blazor router navigation chokes (i.e., it won't navigate anywhere ... it just takes the segment as a value for Text on the Index component and displays it). Even if I do navigate away from such an Index component (e.g., /RouteParameter/xxx to avoid choking the navigation) and then back to Index with a <a href="/">Index</a>, it does work as described with OnInitialized ...

Capture3

Safia ... I think 🤔 ... AFAICT 🤔 ... our coverage is correct for the usual use cases. If so, we can close.

AFAIK, we haven't changed anything with the way route parameters are set in 5.0 so using OnInitialized to set default parameters is the right call. OnInitialized is always called once before the component is rendered, so default parameters should be set there. OnParameterSet is called whenever parameters change, so you might end up overriding parameters inadvertently if default parameters are set there.

@GaurdRex, I tested again on an inner page, and it works the same way. The parameter is null on the third link. If you use OnParametersSet, then it is set to 1 correctly. Click the first link, the second link, then the third link. On the third one, the parameter is null.

@page "/counter"
@page "/counter/{CurrentCount:int}"
<h1>Counter</h1>
<p>Current count: @CurrentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
<ul>
    <li><a href="/counter/42">Navigate to /counter/42</a></li>
    <li><a href="/counter/123">Navigate to /counter/123</a></li>
    <li><a href="/counter/">Navigate to /counter</a></li>
</ul>
@code {
    [Parameter]
    public int? CurrentCount { get; set; }
    void IncrementCount()
    {
        CurrentCount++;
    }

    protected override void OnInitialized()
    {
        base.OnInitialized();
        CurrentCount = CurrentCount ?? 1;
    }
    //protected override void OnParametersSet()
    //{
    //    base.OnInitialized();
    //    CurrentCount = CurrentCount ?? 1;
    //}

}

Blazor University makes the same point I am trying to make.

@gregoryagu ... We don't document ...

@page "/counter"
@page "/counter/{CurrentCount:int}"

The following should work (should because I haven't used the constraints in testing ... yet) ...

@page "/counter/{CurrentCount?:int}

You might need to open a product unit issue to discuss it further and then they/you can let me know what behavior(s)/example(s) would be best.

https://github.com/dotnet/aspnetcore/issues

I really shouldn't guess, and @captainsafia doesn't have additional info .... and she knows a lot more is is a lot smarter than green dinosaurs! :smile: lol

You should use on OnParameterSet if you have transitions in your app that render the same component (for example, go from "/customer" to "/customer/5" or vice versa.

I'll add it to the coverage.

Was this page helpful?
0 / 5 - 0 ratings