Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move example code to sample apps #31341

Merged
merged 1 commit into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 10 additions & 42 deletions aspnetcore/blazor/components/cascading-values-and-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,65 +29,33 @@ Root-level cascading values can be registered for the entire component hierarchy

The following class is used in this section's examples.

`Daleks.cs`:
`Dalek.cs`:

```csharp
// "Dalek" ©Terry Nation https://www.imdb.com/name/nm0622334/
// "Doctor Who" ©BBC https://www.bbc.co.uk/programmes/b006q2x0

namespace BlazorSample;

public class Daleks
{
public int Units { get; set; }
}
```
:::code language="csharp" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Dalek.cs":::

The following registrations are made in the app's `Program` file:

* `Daleks` with a property value for `Units` is registered as a fixed cascading value.
* A second `Daleks` registration with a different property value for `Units` is named "`AlphaGroup`".
* `Dalek` with a property value for `Units` is registered as a fixed cascading value.
* A second `Dalek` registration with a different property value for `Units` is named "`AlphaGroup`".

```csharp
builder.Services.AddCascadingValue(sp => new Daleks { Units = 123 });
builder.Services.AddCascadingValue("AlphaGroup", sp => new Daleks { Units = 456 });
builder.Services.AddCascadingValue(sp => new Dalek { Units = 123 });
builder.Services.AddCascadingValue("AlphaGroup", sp => new Dalek { Units = 456 });
```

The following `Daleks` component displays the cascaded values.

`Daleks.razor`:

```razor
@page "/daleks"

<h1>Root-level cascading value registration example</h1>

<ul>
<li>Dalek Units: @Daleks?.Units</li>
<li>Alpha Group Dalek Units: @AlphaGroupDaleks?.Units</li>
</ul>

<p>
Dalek© <a href="https://www.imdb.com/name/nm0622334/">Terry Nation</a><br>
Doctor Who© <a href="https://www.bbc.co.uk/programmes/b006q2x0">BBC</a>
</p>

@code {
[CascadingParameter]
public Daleks? Daleks { get; set; }

[CascadingParameter(Name = "AlphaGroup")]
public Daleks? AlphaGroupDaleks { get; set; }
}
```
:::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Daleks.razor":::

In the following example, `Daleks` is registered as a cascading value using [`CascadingValueSource<T>`](xref:Microsoft.AspNetCore.Components.CascadingValueSource%601), where `<T>` is the type. The `isFixed` flag indicates whether the value is fixed. If false, all recipients are subscribed for update notifications, which are issued by calling <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601.NotifyChangedAsync%2A>. Subscriptions create overhead and reduce performance, so set `isFixed` to `true` if the value doesn't change.
In the following example, `Dalek` is registered as a cascading value using [`CascadingValueSource<T>`](xref:Microsoft.AspNetCore.Components.CascadingValueSource%601), where `<T>` is the type. The `isFixed` flag indicates whether the value is fixed. If false, all recipients are subscribed for update notifications, which are issued by calling <xref:Microsoft.AspNetCore.Components.CascadingValueSource%601.NotifyChangedAsync%2A>. Subscriptions create overhead and reduce performance, so set `isFixed` to `true` if the value doesn't change.

```csharp
builder.Services.AddCascadingValue(sp =>
{
var daleks = new Daleks { Units = 789 };
var source = new CascadingValueSource<Daleks>(daleks, isFixed: false);
var dalek = new Dalek { Units = 789 };
var source = new CascadingValueSource<Dalek>(dalek, isFixed: false);
return source;
});
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ To choose among these approaches, reusable Razor component authors must make a c

In most cases, reusable component authors should **not** specify a render mode, even when interactivity is required. This is because the component author doesn't know whether the app enables support for <xref:Microsoft.AspNetCore.Components.Web.RenderMode.InteractiveServer>, <xref:Microsoft.AspNetCore.Components.Web.RenderMode.InteractiveWebAssembly>, or both with <xref:Microsoft.AspNetCore.Components.Web.RenderMode.InteractiveAuto>. By not specifying a `@rendermode`, the component author leaves the choice to the app developer.

Even if the component author thinks that interactivity is required, there may still be cases where an app author considers it sufficient to use static SSR alone. For example, a draggable, zoomable map component may seem to require interactivity. However, some scenarios may only call for rendering a static map image and avoiding drag/zoom features.
Even if the component author thinks that interactivity is required, there may still be cases where an app author considers it sufficient to use static SSR alone. For example, a map component with drag and zoom interactivity may seem to require interactivity. However, some scenarios may only call for rendering a static map image and avoiding drag/zoom features.

The only reason why a reusable component author should use the `@rendermode` directive on their component is if the implementation is fundamentally coupled to one specific render mode and would certainly cause an error if used in a different mode. Consider a component with a core purpose of interacting directly with the host OS using Windows or Linux-specific APIs. It might be impossible to use such a component on WebAssembly. If so, it's reasonable to declare `@rendermode InteractiveServer` for the component.

Expand Down
6 changes: 6 additions & 0 deletions aspnetcore/blazor/components/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,12 @@ This can result in a noticeable change in the data displayed in the UI when the

The following code demonstrates a `WeatherForecastService` that avoids the change in data display due to prerendering. The awaited <xref:System.Threading.Tasks.Task.Delay%2A> (`await Task.Delay(...)`) simulates a short delay before returning data from the `GetForecastAsync` method.

Add <xref:Microsoft.Extensions.Caching.Memory.IMemoryCache> services with <xref:Microsoft.Extensions.DependencyInjection.MemoryCacheServiceCollectionExtensions.AddMemoryCache%2A> on the service collection in the app's `Program` file:

```csharp
builder.Services.AddMemoryCache();
```

`WeatherForecastService.cs`:

:::moniker range=">= aspnetcore-8.0"
Expand Down
91 changes: 5 additions & 86 deletions aspnetcore/blazor/components/prerender.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,36 +35,9 @@ Consider the following `PrerenderedCounter1` counter component. The component se

`PrerenderedCounter1.razor`:

```razor
@page "/prerendered-counter-1"
@inject ILogger<PrerenderedCounter1> Logger

<PageTitle>Prerendered Counter 1</PageTitle>

<h1>Prerendered Counter 1</h1>

<p role="status">Current count: @currentCount</p>
:::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/PrerenderedCounter1.razor":::

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount;
private Random r = new Random();

protected override void OnInitialized()
{
currentCount = r.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}

private void IncrementCount()
{
currentCount++;
}
}
```

Run the app and inspect logging from the component:
Run the app and inspect logging from the component. The following is example output:

> :::no-loc text="info: BlazorSample.Components.Pages.PrerenderedCounter1[0]":::
> :::no-loc text=" currentCount set to 41":::
Expand All @@ -78,7 +51,7 @@ To retain the initial value of the counter during prerendering, Blazor supports
To preserve prerendered state, decide what state to persist using the <xref:Microsoft.AspNetCore.Components.PersistentComponentState> service. <xref:Microsoft.AspNetCore.Components.PersistentComponentState.RegisterOnPersisting%2A?displayProperty=nameWithType> registers a callback to persist the component state before the app is paused. The state is retrieved when the app resumes.

> [!IMPORTANT]
> Persisting component state only works during the initial render of a component and not across enhanced page navigations. Currently, the <xref:Microsoft.AspNetCore.Components.PersistentComponentState> service isn't aware of enhanced navigations, and there's no mechanism to deliver state updates to components that are already running. A mechanism to deliver state updates for enhanced navigations is planned for .NET 9, which is targeted for release in late 2024. For more information, see [[Blazor] Support persistent component state across enhanced page navigations (dotnet/aspnetcore #51584)](https://github.com/dotnet/aspnetcore/issues/51584). For more information on enhanced navigation, see <xref:blazor/fundamentals/routing#enhanced-navigation-and-form-handling>.
> Persisting component state only works during the initial render of a component and not across enhanced page navigation events. Currently, the <xref:Microsoft.AspNetCore.Components.PersistentComponentState> service isn't aware of enhanced navigation, and there's no mechanism to deliver state updates to components that are already running. A mechanism to deliver state updates for enhanced navigation is planned for .NET 9, which is targeted for release in late 2024. For more information, see [[Blazor] Support persistent component state across enhanced page navigations (dotnet/aspnetcore #51584)](https://github.com/dotnet/aspnetcore/issues/51584). For more information on enhanced navigation, see <xref:blazor/fundamentals/routing#enhanced-navigation-and-form-handling>.

The following example demonstrates the general pattern:

Expand Down Expand Up @@ -129,63 +102,9 @@ The following counter component example persists counter state during prerenderi

`PrerenderedCounter2.razor`:

```razor
@page "/prerendered-counter-2"
@implements IDisposable
@inject ILogger<PrerenderedCounter2> Logger
@inject PersistentComponentState ApplicationState

<PageTitle>Prerendered Counter 2</PageTitle>

<h1>Prerendered Counter 2</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount;
private Random r = new Random();
private PersistingComponentStateSubscription persistingSubscription;

protected override void OnInitialized()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistCount);

if (!ApplicationState.TryTakeFromJson<int>(
"count", out var restoredCount))
{
currentCount = r.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}
else
{
currentCount = restoredCount!;
Logger.LogInformation("currentCount restored to {Count}", currentCount);
}
}

private Task PersistCount()
{
ApplicationState.PersistAsJson("count", currentCount);

return Task.CompletedTask;
}

void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}

private void IncrementCount()
{
currentCount++;
}
}
```
:::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/PrerenderedCounter2.razor":::

When the component executes, `currentCount` is only set once during prerendering. The value is restored when the component is rerendered:
When the component executes, `currentCount` is only set once during prerendering. The value is restored when the component is rerendered. The following is example output:

> :::no-loc text="info: BlazorSample.Components.Pages.PrerenderedCounter2[0]":::
> :::no-loc text=" currentCount set to 96":::
Expand Down
33 changes: 5 additions & 28 deletions aspnetcore/blazor/components/quickgrid.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,32 +56,9 @@ For example, add the following component to render a grid.

The component assumes that the Interactive Server render mode (`InteractiveServer`) is inherited from a parent component or applied globally to the app, which enables interactive features. For the following example, the only interactive feature is sortable columns.

`QuickGridExample.razor`:
`PromotionGrid.razor`:

```razor
@page "/quickgrid-example"
@using Microsoft.AspNetCore.Components.QuickGrid

<QuickGrid Items="@people">
<PropertyColumn Property="@(p => p.PersonId)" Sortable="true" />
<PropertyColumn Property="@(p => p.Name)" Sortable="true" />
<PropertyColumn Property="@(p => p.PromotionDate)" Format="yyyy-MM-dd" Sortable="true" />
</QuickGrid>

@code {
private record Person(int PersonId, string Name, DateOnly PromotionDate);

private IQueryable<Person> people = new[]
{
new Person(10895, "Jean Martin", new DateOnly(1985, 3, 16)),
new Person(10944, "António Langa", new DateOnly(1991, 12, 1)),
new Person(11203, "Julie Smith", new DateOnly(1958, 10, 10)),
new Person(11205, "Nur Sari", new DateOnly(1922, 4, 27)),
new Person(11898, "Jose Hernandez", new DateOnly(2011, 5, 3)),
new Person(12130, "Kenji Sato", new DateOnly(2004, 1, 9)),
}.AsQueryable();
}
```
:::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/PromotionGrid.razor":::

For an example that uses an <xref:System.Linq.IQueryable> with Entity Framework Core as the queryable data source, see the [`SampleQuickGridComponent` component in the ASP.NET Core Basic Test App (`dotnet/aspnetcore` GitHub repository)](https://github.com/dotnet/aspnetcore/blob/main/src/Components/test/testassets/BasicTestApp/QuickGridTest/SampleQuickGridComponent.razor).

Expand Down Expand Up @@ -122,10 +99,10 @@ Add a ***prerelease*** package reference for the [`Microsoft.AspNetCore.Componen

Add the following component to render a grid.

`QuickGridExample.razor`:
`PromotionGrid.razor`:

```razor
@page "/quickgrid-example"
@page "/promotion-grid"
@using Microsoft.AspNetCore.Components.QuickGrid

<QuickGrid Items="@people">
Expand All @@ -151,6 +128,6 @@ Add the following component to render a grid.

:::moniker-end

Access the component in a browser at the relative path `/quickgrid-example`.
Access the component in a browser at the relative path `/promotion-grid`.

There aren't current plans to extend `QuickGrid` with features that full-blown commercial grids tend to offer, for example, hierarchical rows, drag-to-reorder columns, or Excel-like range selections. If you require advanced features that you don't wish to develop on your own, continue using third-party grids.
58 changes: 2 additions & 56 deletions aspnetcore/blazor/components/virtualization.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,30 +197,7 @@ Use the <xref:Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize%601.

`EmptyContent.razor`:

```razor
@page "/empty-content"

<h1>Empty Content Example</h1>

<Virtualize Items="@stringList">
<ItemContent>
<p>
@context
</p>
</ItemContent>
<EmptyContent>
<p>
There are no strings to display.
</p>
</EmptyContent>
</Virtualize>

@code {
private List<string>? stringList;

protected override void OnInitialized() => stringList ??= new();
}
```
:::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/EmptyContent.razor":::

Change the `OnInitialized` method lambda to see the component display strings:

Expand Down Expand Up @@ -388,38 +365,7 @@ If the <xref:Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize%601>

`VirtualizedTable.razor`:

```razor
@page "/virtualized-table"

<HeadContent>
<style>
html, body { overflow-y: scroll }
</style>
</HeadContent>

<h1>Virtualized Table Example</h1>

<table id="virtualized-table">
<thead style="position: sticky; top: 0; background-color: silver">
<tr>
<th>Item</th>
<th>Another column</th>
</tr>
</thead>
<tbody>
<Virtualize Items="@fixedItems" ItemSize="30" SpacerElement="tr">
<tr @key="context" style="height: 30px;" id="row-@context">
<td>Item @context</td>
<td>Another value</td>
</tr>
</Virtualize>
</tbody>
</table>

@code {
private List<int> fixedItems = Enumerable.Range(0, 1000).ToList();
}
```
:::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/VirtualizedTable.razor":::

In the preceding example, the document root is used as the scroll container, so the `html` and `body` elements are styled with `overflow-y: scroll`. For more information, see the following resources:

Expand Down