From 2d9f5ef2142471cba621c8c7f4d7efc979547b0d Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Tue, 1 Aug 2023 18:03:12 -0400 Subject: [PATCH 01/11] Full-stack UI updates (Components node) 8.0 --- aspnetcore/blazor/components/class-libraries.md | 16 +++++++--------- .../blazor/components/control-head-content.md | 3 +++ aspnetcore/blazor/components/css-isolation.md | 4 ++++ aspnetcore/blazor/components/index.md | 3 +++ aspnetcore/blazor/components/layouts.md | 2 +- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/aspnetcore/blazor/components/class-libraries.md b/aspnetcore/blazor/components/class-libraries.md index e378f912b85c..5986cae7204e 100644 --- a/aspnetcore/blazor/components/class-libraries.md +++ b/aspnetcore/blazor/components/class-libraries.md @@ -55,7 +55,7 @@ If the **Support pages and views** checkbox is selected to support pages and vie ``` - For more information on the `SupportedPlatform` item, see the [Browser compatibility analyzer for Blazor WebAssembly](#browser-compatibility-analyzer-for-blazor-webassembly) section. + For more information on the `SupportedPlatform` item, see the [client-side browser compatibility analyzer](#client-side-browser-compatibility-analyzer) section. :::moniker-end @@ -102,7 +102,7 @@ If the **Support pages and views** checkbox is selected to support pages and vie ``` - For more information on the `SupportedPlatform` item, see the [Browser compatibility analyzer for Blazor WebAssembly](#browser-compatibility-analyzer-for-blazor-webassembly) section. + For more information on the `SupportedPlatform` item, see the [client-side browser compatibility analyzer](#client-side-browser-compatibility-analyzer) section. :::moniker-end @@ -148,7 +148,7 @@ If the `-s|--support-pages-and-views` option is used to support pages and views ``` - For more information on the `SupportedPlatform` item, see the [Browser compatibility analyzer for Blazor WebAssembly](#browser-compatibility-analyzer-for-blazor-webassembly) section. + For more information on the `SupportedPlatform` item, see the [client-side browser compatibility analyzer](#client-side-browser-compatibility-analyzer) section. :::moniker-end @@ -343,9 +343,7 @@ The following background image and stylesheet are used by the RCL's `Component1` } ``` -To provide `Component1`'s `my-component` CSS class, link to the library's stylesheet in the app's `` markup. - -`wwwroot/index.html` file (Blazor WebAssembly) or `Pages/_Host.cshtml` file (Blazor Server): +To provide `Component1`'s `my-component` CSS class, link to the library's stylesheet in the app's `` markup ([location of `` content](xref:blazor/project-structure#location-of-head-content)): ```html @@ -426,11 +424,11 @@ For more information, see when running on WebAssembly. A platform compatibility analyzer warns the developer when the app uses APIs that aren't supported by the app's target platforms. For Blazor WebAssembly apps, this means checking that APIs are supported in browsers. Annotating .NET framework APIs for the compatibility analyzer is an on-going process, so not all .NET framework API is currently annotated. +Client-side apps target the full .NET API surface area, but not all .NET APIs are supported on WebAssembly due to browser sandbox constraints. Unsupported APIs throw when running on WebAssembly. A platform compatibility analyzer warns the developer when the app uses APIs that aren't supported by the app's target platforms. For client-side apps, this means checking that APIs are supported in browsers. Annotating .NET framework APIs for the compatibility analyzer is an on-going process, so not all .NET framework API is currently annotated. -Blazor WebAssembly and RCL projects *automatically* enable browser compatibility checks by adding `browser` as a supported platform with the `SupportedPlatform` MSBuild item. Library developers can manually add the `SupportedPlatform` item to a library's project file to enable the feature: +Blazor Web Apps that enable interactive WebAssembly components, Blazor WebAssembly apps, and RCL projects *automatically* enable browser compatibility checks by adding `browser` as a supported platform with the `SupportedPlatform` MSBuild item. Library developers can manually add the `SupportedPlatform` item to a library's project file to enable the feature: ```xml diff --git a/aspnetcore/blazor/components/control-head-content.md b/aspnetcore/blazor/components/control-head-content.md index 080e431e686b..541ad32604a5 100644 --- a/aspnetcore/blazor/components/control-head-content.md +++ b/aspnetcore/blazor/components/control-head-content.md @@ -42,6 +42,9 @@ The following example sets the page's title and description using Razor. *This section applies to prerendered Blazor WebAssembly apps and Blazor Server apps.* + + When [Razor components are prerendered](xref:blazor/components/prerendering-and-integration), the use of a layout page (`_Layout.cshtml`) is required to control `` content with the and components. The reason for this requirement is that components that control `` content must be rendered before the layout with the component. **This order of rendering is required to control head content.** If the shared `_Layout.cshtml` file doesn't have a [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper) for a component, add it to the `` elements. diff --git a/aspnetcore/blazor/components/css-isolation.md b/aspnetcore/blazor/components/css-isolation.md index 72cb8bb04a9b..adee0bf441fa 100644 --- a/aspnetcore/blazor/components/css-isolation.md +++ b/aspnetcore/blazor/components/css-isolation.md @@ -57,12 +57,16 @@ CSS isolation occurs at build time. Blazor rewrites CSS selectors to match marku ``` +:::moniker range="< aspnetcore-8.0" + The following example is from a hosted Blazor WebAssembly **:::no-loc text="Client":::** app. The app's assembly name is `BlazorSample.Client`, and the `` is added by the Blazor WebAssembly project template when the project is created with the Hosted option (`-ho|--hosted` option using the .NET CLI or **ASP.NET Core Hosted** checkbox using Visual Studio): ```html ``` +:::moniker-end + Within the bundled file, each component is associated with a scope identifier. For each styled component, an HTML attribute is appended with the format `b-{STRING}`, where the `{STRING}` placeholder is a ten-character string generated by the framework. The identifier is unique for each app. In the rendered `Counter` component, Blazor appends a scope identifier to the `h1` element: ```html diff --git a/aspnetcore/blazor/components/index.md b/aspnetcore/blazor/components/index.md index a0dd4ec4775f..8e954d1a80e6 100644 --- a/aspnetcore/blazor/components/index.md +++ b/aspnetcore/blazor/components/index.md @@ -1366,6 +1366,9 @@ In the preceding code, the CSS selector, `#app`, indicates that the `App` compon
... ``` + + MVC and Razor Pages apps can also use the [Component Tag Helper](xref:Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper) to register statically-rendered Blazor WebAssembly root components: ```cshtml diff --git a/aspnetcore/blazor/components/layouts.md b/aspnetcore/blazor/components/layouts.md index a939d9328de9..cd5e1b2decf5 100644 --- a/aspnetcore/blazor/components/layouts.md +++ b/aspnetcore/blazor/components/layouts.md @@ -94,7 +94,7 @@ In an app created from a [Blazor project template](xref:blazor/project-structure [Blazor's CSS isolation feature](xref:blazor/components/css-isolation) applies isolated CSS styles to the `MainLayout` component. By convention, the styles are provided by the accompanying stylesheet of the same name, `Shared/MainLayout.razor.css`. The ASP.NET Core framework implementation of the stylesheet is available for inspection in the ASP.NET Core reference source (`dotnet/aspnetcore` GitHub repository): * [Blazor Server `MainLayout.razor.css`](https://github.com/dotnet/aspnetcore/blob/release/7.0/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Shared/MainLayout.razor.css) -* [Blazor WebAssembly `MainLayout.razor.css`](https://github.com/dotnet/aspnetcore/blob/release/7.0/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/Shared/MainLayout.razor.css) +* [Blazor WebAssembly `MainLayout.razor.css`](https://github.com/dotnet/aspnetcore/blob/main/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Shared/MainLayout.razor.css) [!INCLUDE[](~/includes/aspnetcore-repo-ref-source-links.md)] From e779529b51e5d921f8b00fd9c206314311fece8b Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Wed, 2 Aug 2023 08:45:46 -0400 Subject: [PATCH 02/11] Updates --- .../blazor/components/control-head-content.md | 3 - aspnetcore/blazor/components/index.md | 20 ++++- .../blazor/components/js-spa-frameworks.md | 75 ++++++++++++++++++- aspnetcore/blazor/components/layouts.md | 13 +++- aspnetcore/blazor/components/lifecycle.md | 30 +++++++- aspnetcore/blazor/components/quickgrid.md | 13 +--- aspnetcore/blazor/components/rendering.md | 2 +- .../components/synchronization-context.md | 4 +- 8 files changed, 137 insertions(+), 23 deletions(-) diff --git a/aspnetcore/blazor/components/control-head-content.md b/aspnetcore/blazor/components/control-head-content.md index 541ad32604a5..080e431e686b 100644 --- a/aspnetcore/blazor/components/control-head-content.md +++ b/aspnetcore/blazor/components/control-head-content.md @@ -42,9 +42,6 @@ The following example sets the page's title and description using Razor. *This section applies to prerendered Blazor WebAssembly apps and Blazor Server apps.* - - When [Razor components are prerendered](xref:blazor/components/prerendering-and-integration), the use of a layout page (`_Layout.cshtml`) is required to control `` content with the and components. The reason for this requirement is that components that control `` content must be rendered before the layout with the component. **This order of rendering is required to control head content.** If the shared `_Layout.cshtml` file doesn't have a [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper) for a component, add it to the `` elements. diff --git a/aspnetcore/blazor/components/index.md b/aspnetcore/blazor/components/index.md index 8e954d1a80e6..e61eb02dc264 100644 --- a/aspnetcore/blazor/components/index.md +++ b/aspnetcore/blazor/components/index.md @@ -1348,19 +1348,33 @@ Whitespace isn't preserved from the preceding markup: A *root Razor component* is the first component loaded of any component hierarchy created by the app. -In an app created from the Blazor Server project template, the `App` component (`App.razor`) is created as the default root component in `Pages/_Host.cshtml` using the [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper): +:::moniker range=">= aspnetcore-8.0" + +In an app created from the Blazor Web App project template, the `App` component (`App.razor`) is specified as the default root component by the type parameter declared for the call to [`MapRazorComponents`](xref:Microsoft.AspNetCore.Builder.RazorComponentsEndpointRouteBuilderExtensions.MapRazorComponents%2A) in the server-side `Program` file. The following example shows the use of the `App` component as the root component, which is the default for an app created from the Blazor project template: + +```csharp +app.MapRazorComponents(); +``` + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + +In an app created from the Blazor Server project template, the `App` component (`App.razor`) is specified as the default root component in `Pages/_Host.cshtml` using the [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper): ```cshtml ``` -In an app created from the Blazor WebAssembly project template, the `App` component (`App.razor`) is created as the default root component in `Program.cs`: +:::moniker-end + +In an app created from the Blazor WebAssembly project template, the `App` component (`App.razor`) is specified as the default root component in the `Program` file: ```csharp builder.RootComponents.Add("#app"); ``` -In the preceding code, the CSS selector, `#app`, indicates that the `App` component is created for the `
` in `wwwroot/index.html` with an `id` of `app`: +In the preceding code, the CSS selector, `#app`, indicates that the `App` component is specified for the `
` in `wwwroot/index.html` with an `id` of `app`: ```html
... diff --git a/aspnetcore/blazor/components/js-spa-frameworks.md b/aspnetcore/blazor/components/js-spa-frameworks.md index 96f871296df9..84cd3a7a6a1b 100644 --- a/aspnetcore/blazor/components/js-spa-frameworks.md +++ b/aspnetcore/blazor/components/js-spa-frameworks.md @@ -51,6 +51,23 @@ One or more initializer functions can be created and called by different compone The following example demonstrates the dynamic registration of the preceding `Quote` component with "`quote`" as the identifier. +:::moniker range=">= aspnetcore-8.0" + +* In a Blazor Web App app, modify the call to in the server-side `Program` file: + + ```csharp + builder.Services.AddRazorComponents() + .AddServerComponents(options => + { + options.RootComponents.RegisterForJavaScript(identifier: "quote", + javaScriptInitializer: "initializeComponent"); + }); + ``` + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + * In a Blazor Server app, modify the call to in `Program.cs`: ```csharp @@ -61,6 +78,8 @@ The following example demonstrates the dynamic registration of the preceding `Qu }); ``` +:::moniker-end + * In a Blazor WebAssembly app, call on in `Program.cs`: ```csharp @@ -207,6 +226,31 @@ Add a package reference for [`Microsoft.AspNetCore.Components.CustomElements`](h [!INCLUDE[](~/includes/package-reference.md)] +:::moniker range=">= aspnetcore-8.0" + +### Blazor Web App registration + +To register a root component as a custom element in a Blazor Web App, modify the call to in the server-side `Program` file. The following example registers the `Counter` component with the custom HTML element `my-counter`: + + + +```csharp +builder.Services.AddRazorComponents() + .AddServerComponents(options => + { + options.RootComponents.RegisterCustomElement("my-counter"); + }); +``` + +> [!NOTE] +> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the server-side `Program` file. + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + ### Blazor Server registration To register a root component as a custom element in a Blazor Server app, modify the call to in `Program.cs`. The following example registers the `Counter` component with the custom HTML element `my-counter`: @@ -219,7 +263,9 @@ builder.Services.AddServerSideBlazor(options => ``` > [!NOTE] -> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) in the `Program.cs` file. +> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the `Program.cs` file. + +:::moniker-end ### Blazor WebAssembly registration @@ -230,7 +276,7 @@ builder.RootComponents.RegisterCustomElement("my-counter"); ``` > [!NOTE] -> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) in the `Program.cs` file. +> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the `Program.cs` file. ### Use the registered custom element @@ -305,7 +351,28 @@ Supported parameter types: Register a root component as a custom element: -* In a Blazor Server app, modify the call to in `Program.cs`: +:::moniker range=">= aspnetcore-8.0" + + + +* In a Blazor Web App, modify the call to in the server-side `Program` file: + + ```csharp + builder.Services.AddRazorComponents() + .AddServerComponents(options => + { + options.RootComponents.RegisterCustomElement("my-counter"); + }); + ``` + > [!NOTE] + > The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the server-side `Program` file. + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + +* In a Blazor Server app, modify the call to in `Program.cs`: ```csharp builder.Services.AddServerSideBlazor(options => @@ -317,6 +384,8 @@ Register a root component as a custom element: > [!NOTE] > The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) in the `Program.cs` file. +:::moniker-end + * In a Blazor WebAssembly app, call `RegisterAsCustomElement` on in `Program.cs`: ```csharp diff --git a/aspnetcore/blazor/components/layouts.md b/aspnetcore/blazor/components/layouts.md index cd5e1b2decf5..8af8b15bd801 100644 --- a/aspnetcore/blazor/components/layouts.md +++ b/aspnetcore/blazor/components/layouts.md @@ -89,7 +89,18 @@ In an app created from a [Blazor project template](xref:blazor/project-structure :::moniker-end -:::moniker range=">= aspnetcore-5.0" +:::moniker range=">= aspnetcore-8.0" + +[Blazor's CSS isolation feature](xref:blazor/components/css-isolation) applies isolated CSS styles to the `MainLayout` component. By convention, the styles are provided by the accompanying stylesheet of the same name, `Shared/MainLayout.razor.css`. The ASP.NET Core framework implementation of the stylesheet is available for inspection in the ASP.NET Core reference source (`dotnet/aspnetcore` GitHub repository): + +* [Blazor Web App `MainLayout.razor.css`](https://github.com/dotnet/aspnetcore/blob/main/src/ProjectTemplates/Web.ProjectTemplates/content/Components-CSharp/Shared/MainLayout.razor.css) +* [Blazor WebAssembly `MainLayout.razor.css`](https://github.com/dotnet/aspnetcore/blob/main/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Shared/MainLayout.razor.css) + +[!INCLUDE[](~/includes/aspnetcore-repo-ref-source-links.md)] + +:::moniker-end + +:::moniker range=">= aspnetcore-5.0 < aspnetcore-8.0" [Blazor's CSS isolation feature](xref:blazor/components/css-isolation) applies isolated CSS styles to the `MainLayout` component. By convention, the styles are provided by the accompanying stylesheet of the same name, `Shared/MainLayout.razor.css`. The ASP.NET Core framework implementation of the stylesheet is available for inspection in the ASP.NET Core reference source (`dotnet/aspnetcore` GitHub repository): diff --git a/aspnetcore/blazor/components/lifecycle.md b/aspnetcore/blazor/components/lifecycle.md index ca02a9932b95..f7fb39c40b8b 100644 --- a/aspnetcore/blazor/components/lifecycle.md +++ b/aspnetcore/blazor/components/lifecycle.md @@ -151,8 +151,22 @@ Blazor apps that prerender their content on the server call + +:::moniker range=">= aspnetcore-8.0" + +To prevent developer code in from running twice when prerendering, see the [Stateful reconnection after prerendering](#stateful-reconnection-after-prerendering) section. Although the content in the section focuses on Blazor Web Apps and stateful SignalR *reconnection*, the scenario for prerendering client-side rendered (CSR) WebAssembly components () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + To prevent developer code in from running twice when prerendering, see the [Stateful reconnection after prerendering](#stateful-reconnection-after-prerendering) section. Although the content in the section focuses on Blazor Server and stateful SignalR *reconnection*, the scenario for prerendering in hosted Blazor WebAssembly apps () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . +:::moniker-end + While a Blazor app is prerendering, certain actions, such as calling into JavaScript (JS interop), aren't possible. Components may need to render differently when prerendered. For more information, see the [Prerendering with JavaScript interop](#prerendering-with-javascript-interop) section. If event handlers are provided in developer code, unhook them on disposal. For more information, see the [Component disposal with `IDisposable` `IAsyncDisposable`](#component-disposal-with-idisposable-and-iasyncdisposable) section. @@ -368,8 +382,22 @@ The following code demonstrates an updated `WeatherForecastService` in a templat For more information on the , see . + + +:::moniker range=">= aspnetcore-8.0" + +Although the content in this section focuses on Blazor Web Apps and stateful SignalR *reconnection*, the scenario for prerendering client-side rendered (CSR) WebAssembly components () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + Although the content in this section focuses on Blazor Server and stateful SignalR *reconnection*, the scenario for prerendering in hosted Blazor WebAssembly apps () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . +:::moniker-end + ## Prerendering with JavaScript interop [!INCLUDE[](~/blazor/includes/prerendering.md)] @@ -398,7 +426,7 @@ At a minimum, always dispose objects created on the .NET side to avoid leaking . For more information, see . -For guidance on in Blazor Server apps when a circuit is disconnected, see . For general JavaScript interop error handling guidance, see the *JavaScript interop* section in . +For guidance on in Blazor Server apps when a circuit is disconnected, see . For general JavaScript interop error handling guidance, see the *JavaScript interop* section in . ### Synchronous `IDisposable` diff --git a/aspnetcore/blazor/components/quickgrid.md b/aspnetcore/blazor/components/quickgrid.md index f775ed87f49b..eeaf5d331ef6 100644 --- a/aspnetcore/blazor/components/quickgrid.md +++ b/aspnetcore/blazor/components/quickgrid.md @@ -22,6 +22,10 @@ Add a ***prerelease*** package reference for the [`Microsoft.AspNetCore.Componen [!INCLUDE[](~/includes/package-reference.md)] +## Sample app + +For various `QuickGrid` demonstrations, see the [**QuickGrid for Blazor** sample app](https://aspnet.github.io/quickgridsamples/). The demo site is hosted on GitHub Pages. The site loads fast thanks to static prerendering using the community-maintained [`BlazorWasmPrerendering.Build` GitHub project](https://github.com/jsakamoto/BlazorWasmPreRendering.Build). + ## `QuickGrid` implementation To implement a `QuickGrid` component: @@ -141,12 +145,3 @@ Add the following component to render a grid. Access the component in a browser at the relative path `/quickgrid-example`. 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. - -:::moniker range="< aspnetcore-8.0" - -For various `QuickGrid` demonstrations, see the [**QuickGrid for Blazor** app](https://aspnet.github.io/quickgridsamples/). The demo site is built using Blazor WebAssembly and is hosted on GitHub Pages. The site loads fast thanks to static prerendering using the community-maintained [`BlazorWasmPrerendering.Build` GitHub project](https://github.com/jsakamoto/BlazorWasmPreRendering.Build). - -> [!WARNING] -> The `QuickGrid` component is in preview for ASP.NET Core 7.x. You're welcome to use it in production if it meets your needs, but it isn't officially supported until ASP.NET Core 8.0 or later. - -:::moniker-end diff --git a/aspnetcore/blazor/components/rendering.md b/aspnetcore/blazor/components/rendering.md index 3b820b0f9a01..570fbf657034 100644 --- a/aspnetcore/blazor/components/rendering.md +++ b/aspnetcore/blazor/components/rendering.md @@ -239,7 +239,7 @@ One way to deal with this scenario is to provide a *state management* class, oft For approaches to manage state, see the following resources: -* [In-memory state container service (Blazor Server)](xref:blazor/state-management?pivots=server#in-memory-state-container-service-server) ([Blazor WebAssembly equivalent](xref:blazor/state-management?pivots=webassembly#in-memory-state-container-service-server)) section of the *State management* article. +* [Server-side in-memory state container service](xref:blazor/state-management?pivots=server#in-memory-state-container-service-server) ([client-side equivalent](xref:blazor/state-management?pivots=webassembly#in-memory-state-container-service-wasm)) section of the *State management* article. * [Pass data across a component hierarchy](xref:blazor/components/cascading-values-and-parameters#pass-data-across-a-component-hierarchy) using cascading values and parameters. * [Bind across more than two components](xref:blazor/components/data-binding#bind-across-more-than-two-components) using data bindings. diff --git a/aspnetcore/blazor/components/synchronization-context.md b/aspnetcore/blazor/components/synchronization-context.md index 202f1c2e910c..36f341b8fc73 100644 --- a/aspnetcore/blazor/components/synchronization-context.md +++ b/aspnetcore/blazor/components/synchronization-context.md @@ -86,14 +86,14 @@ In the event a component must be updated based on an external event, such as a t Register the services: -* In a Blazor WebAssembly app, register the services as singletons in `Program.cs`: +* For client-side development, register the services as singletons in the client-side `Program` file: ```csharp builder.Services.AddSingleton(); builder.Services.AddSingleton(); ``` -* In a Blazor Server app, register the services as scoped in `Program.cs`: +* For server-side development, register the services as scoped in the server-side `Program` file: ```csharp builder.Services.AddScoped(); From edfd9b8ac763209605ccf6b630a4ce6b2b1fc12f Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Wed, 2 Aug 2023 09:45:28 -0400 Subject: [PATCH 03/11] Updates --- aspnetcore/blazor/components/index.md | 6 +++- .../blazor/components/js-spa-frameworks.md | 29 ++++--------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/aspnetcore/blazor/components/index.md b/aspnetcore/blazor/components/index.md index e61eb02dc264..70bb28fc1db9 100644 --- a/aspnetcore/blazor/components/index.md +++ b/aspnetcore/blazor/components/index.md @@ -1348,6 +1348,8 @@ Whitespace isn't preserved from the preceding markup: A *root Razor component* is the first component loaded of any component hierarchy created by the app. +:::moniker-end + :::moniker range=">= aspnetcore-8.0" In an app created from the Blazor Web App project template, the `App` component (`App.razor`) is specified as the default root component by the type parameter declared for the call to [`MapRazorComponents`](xref:Microsoft.AspNetCore.Builder.RazorComponentsEndpointRouteBuilderExtensions.MapRazorComponents%2A) in the server-side `Program` file. The following example shows the use of the `App` component as the root component, which is the default for an app created from the Blazor project template: @@ -1358,7 +1360,7 @@ app.MapRazorComponents(); :::moniker-end -:::moniker range="< aspnetcore-8.0" +:::moniker range=">= aspnetcore-6.0 < aspnetcore-8.0" In an app created from the Blazor Server project template, the `App` component (`App.razor`) is specified as the default root component in `Pages/_Host.cshtml` using the [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper): @@ -1368,6 +1370,8 @@ In an app created from the Blazor Server project template, the `App` component ( :::moniker-end +:::moniker range=">= aspnetcore-6.0" + In an app created from the Blazor WebAssembly project template, the `App` component (`App.razor`) is specified as the default root component in the `Program` file: ```csharp diff --git a/aspnetcore/blazor/components/js-spa-frameworks.md b/aspnetcore/blazor/components/js-spa-frameworks.md index 84cd3a7a6a1b..a42569837824 100644 --- a/aspnetcore/blazor/components/js-spa-frameworks.md +++ b/aspnetcore/blazor/components/js-spa-frameworks.md @@ -226,6 +226,8 @@ Add a package reference for [`Microsoft.AspNetCore.Components.CustomElements`](h [!INCLUDE[](~/includes/package-reference.md)] +:::moniker-end + :::moniker range=">= aspnetcore-8.0" ### Blazor Web App registration @@ -249,7 +251,7 @@ builder.Services.AddRazorComponents() :::moniker-end -:::moniker range="< aspnetcore-8.0" +:::moniker range=">= aspnetcore-7.0 < aspnetcore-8.0" ### Blazor Server registration @@ -267,6 +269,8 @@ builder.Services.AddServerSideBlazor(options => :::moniker-end +:::moniker range=">= aspnetcore-7.0" + ### Blazor WebAssembly registration To register a root component as a custom element in a Blazor WebAssembly app, call `RegisterCustomElement` on in `Program.cs`. The following example registers the `Counter` component with the custom HTML element `my-counter`: @@ -351,27 +355,6 @@ Supported parameter types: Register a root component as a custom element: -:::moniker range=">= aspnetcore-8.0" - - - -* In a Blazor Web App, modify the call to in the server-side `Program` file: - - ```csharp - builder.Services.AddRazorComponents() - .AddServerComponents(options => - { - options.RootComponents.RegisterCustomElement("my-counter"); - }); - ``` - > [!NOTE] - > The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the server-side `Program` file. - -:::moniker-end - -:::moniker range="< aspnetcore-8.0" - * In a Blazor Server app, modify the call to in `Program.cs`: ```csharp @@ -384,8 +367,6 @@ Register a root component as a custom element: > [!NOTE] > The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) in the `Program.cs` file. -:::moniker-end - * In a Blazor WebAssembly app, call `RegisterAsCustomElement` on in `Program.cs`: ```csharp From 83a0be7233f5ea2b44536e87dd25b1043fef3641 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Wed, 2 Aug 2023 10:32:41 -0400 Subject: [PATCH 04/11] Updates --- .../blazor/components/class-libraries.md | 9 ++- .../blazor/components/control-head-content.md | 2 +- .../blazor/components/js-spa-frameworks.md | 8 +-- aspnetcore/blazor/components/lifecycle.md | 64 ++++++++++--------- aspnetcore/blazor/components/quickgrid.md | 2 +- .../components/synchronization-context.md | 2 +- .../blazor/fundamentals/static-files.md | 20 ++++++ aspnetcore/blazor/host-and-deploy/index.md | 14 ++++ .../multiple-hosted-webassembly.md | 2 +- .../blazor/host-and-deploy/webassembly.md | 21 ++++++ 10 files changed, 105 insertions(+), 39 deletions(-) diff --git a/aspnetcore/blazor/components/class-libraries.md b/aspnetcore/blazor/components/class-libraries.md index 5986cae7204e..3365ccbaf79f 100644 --- a/aspnetcore/blazor/components/class-libraries.md +++ b/aspnetcore/blazor/components/class-libraries.md @@ -418,9 +418,16 @@ For more information, see . + + +For more information, see . + +:::moniker-end :::moniker range=">= aspnetcore-5.0" diff --git a/aspnetcore/blazor/components/control-head-content.md b/aspnetcore/blazor/components/control-head-content.md index 080e431e686b..88c6fabeb032 100644 --- a/aspnetcore/blazor/components/control-head-content.md +++ b/aspnetcore/blazor/components/control-head-content.md @@ -103,7 +103,7 @@ In Blazor Server apps created from the Blazor Server project template, a [Compon :::moniker-end -In an app created from the Blazor WebAssembly project template, the component is added to the collection of the in `Program.cs`: +In an app created from the Blazor WebAssembly project template, the component is added to the collection of the in the client-side `Program` file: ```csharp builder.RootComponents.Add("head::after"); diff --git a/aspnetcore/blazor/components/js-spa-frameworks.md b/aspnetcore/blazor/components/js-spa-frameworks.md index a42569837824..971eeb97fd74 100644 --- a/aspnetcore/blazor/components/js-spa-frameworks.md +++ b/aspnetcore/blazor/components/js-spa-frameworks.md @@ -34,7 +34,7 @@ The example in this section renders the following Razor component into a page vi } ``` -In `Program.cs`, add the namespace for the location of the component. The following example assumes that the `Quote` component is in the app's `Shared` folder, and the app's namespace is `BlazorSample`: +In the `Program` file, add the namespace for the location of the component. The following example assumes that the `Quote` component is in the app's `Shared` folder, and the app's namespace is `BlazorSample`: ```csharp using BlazorSample.Shared; @@ -80,7 +80,7 @@ The following example demonstrates the dynamic registration of the preceding `Qu :::moniker-end -* In a Blazor WebAssembly app, call on in `Program.cs`: +* In a Blazor WebAssembly app, call on in the client-side `Program` file: ```csharp builder.RootComponents.RegisterForJavaScript(identifier: "quote", @@ -273,14 +273,14 @@ builder.Services.AddServerSideBlazor(options => ### Blazor WebAssembly registration -To register a root component as a custom element in a Blazor WebAssembly app, call `RegisterCustomElement` on in `Program.cs`. The following example registers the `Counter` component with the custom HTML element `my-counter`: +To register a root component as a custom element in a Blazor WebAssembly app, call `RegisterCustomElement` on in the client-side `Program` file. The following example registers the `Counter` component with the custom HTML element `my-counter`: ```csharp builder.RootComponents.RegisterCustomElement("my-counter"); ``` > [!NOTE] -> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the `Program.cs` file. +> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the client-side `Program` file. ### Use the registered custom element diff --git a/aspnetcore/blazor/components/lifecycle.md b/aspnetcore/blazor/components/lifecycle.md index f7fb39c40b8b..85e807b42554 100644 --- a/aspnetcore/blazor/components/lifecycle.md +++ b/aspnetcore/blazor/components/lifecycle.md @@ -151,12 +151,12 @@ Blazor apps that prerender their content on the server call -:::moniker range=">= aspnetcore-8.0" - To prevent developer code in from running twice when prerendering, see the [Stateful reconnection after prerendering](#stateful-reconnection-after-prerendering) section. Although the content in the section focuses on Blazor Web Apps and stateful SignalR *reconnection*, the scenario for prerendering client-side rendered (CSR) WebAssembly components () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . :::moniker-end @@ -311,33 +311,34 @@ For more information on component rendering and when to call is overridden to asynchronously receive forecast data (`forecasts`). When `forecasts` is `null`, a loading message is displayed to the user. After the `Task` returned by completes, the component is rerendered with the updated state. - -`Pages/FetchData.razor` in the Blazor Server template: - -:::moniker range=">= aspnetcore-7.0" - -:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_Server/Pages/lifecycle/FetchData.razor" highlight="9,21,25"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0" - -:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_Server/Pages/lifecycle/FetchData.razor" highlight="9,21,25"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0" +In the following component, is overridden to asynchronously provide movie rating data (`movies`). When `movies` is `null`, a loading message is displayed to the user. After the `Task` returned by completes, the component is rerendered with the updated state. -:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_Server/Pages/lifecycle/FetchData.razor" highlight="9,21,25"::: - -:::moniker-end +```razor +

Sci-Fi Movie Ratings

-:::moniker range="< aspnetcore-5.0" +@if (movies == null) +{ +

Loading...

+} +else +{ +
    + @foreach (var movie in movies) + { +
  • @movie.Title — @movie.Rating
  • + } +
+} -:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_Server/Pages/lifecycle/FetchData.razor" highlight="9,21,25"::: +@code { + private Movies[]? movies; -:::moniker-end + protected override async Task OnInitializedAsync() + { + movies = await GetMovieRatings(DateTime.Now); + } +} +``` ## Handle errors @@ -345,14 +346,14 @@ For information on handling errors during lifecycle method execution, see is , the component is initially rendered statically as part of the page. Once the browser establishes a SignalR connection back to the server, the component is rendered *again* and interactive. If the [`OnInitialized{Async}`](#component-initialization-oninitializedasync) lifecycle method for initializing the component is present, the method is executed *twice*: +When prerendering on the server, a component is initially rendered statically as part of the page. Once the browser establishes a SignalR connection back to the server, the component is rendered *again* and interactive. If the [`OnInitialized{Async}`](#component-initialization-oninitializedasync) lifecycle method for initializing the component is present, the method is executed *twice*: * When the component is prerendered statically. * After the server connection has been established. -This can result in a noticeable change in the data displayed in the UI when the component is finally rendered. To avoid this double-rendering behavior in a Blazor Server app, pass in an identifier to cache the state during prerendering and to retrieve the state after prerendering. +This can result in a noticeable change in the data displayed in the UI when the component is finally rendered. To avoid this behavior, pass in an identifier to cache the state during prerendering and to retrieve the state after prerendering. -The following code demonstrates an updated `WeatherForecastService` in a template-based Blazor Server app that avoids the double rendering. In the following example, the awaited (`await Task.Delay(...)`) simulates a short delay before returning data from the `GetForecastAsync` method. +The following code demonstrates a `WeatherForecastService` that avoids the change in data display due to prerendering. The awaited (`await Task.Delay(...)`) simulates a short delay before returning data from the `GetForecastAsync` method. `WeatherForecastService.cs`: @@ -426,7 +427,7 @@ At a minimum, always dispose objects created on the .NET side to avoid leaking . For more information, see . -For guidance on in Blazor Server apps when a circuit is disconnected, see . For general JavaScript interop error handling guidance, see the *JavaScript interop* section in . +For guidance on when a circuit is disconnected, see . For general JavaScript interop error handling guidance, see the *JavaScript interop* section in . ### Synchronous `IDisposable` @@ -731,3 +732,6 @@ In the following example: ## Blazor Server reconnection events The component lifecycle events covered in this article operate separately from [Blazor Server's reconnection event handlers](xref:blazor/fundamentals/signalr#reflect-the-connection-state-in-the-ui-blazor-server). When a Blazor Server app loses its SignalR connection to the client, only UI updates are interrupted. UI updates are resumed when the connection is re-established. For more information on circuit handler events and configuration, see . + + diff --git a/aspnetcore/blazor/components/quickgrid.md b/aspnetcore/blazor/components/quickgrid.md index eeaf5d331ef6..d85e845cdae3 100644 --- a/aspnetcore/blazor/components/quickgrid.md +++ b/aspnetcore/blazor/components/quickgrid.md @@ -90,7 +90,7 @@ To use Entity Framework (EF) Core as the data source: [!INCLUDE[](~/includes/package-reference.md)] -* Call `AddQuickGridEntityFrameworkAdapter` on the service collection in `Program.cs` to register an EF-aware implementation of `IAsyncQueryExecutor`: +* Call `AddQuickGridEntityFrameworkAdapter` on the service collection in the `Program` file to register an EF-aware implementation of `IAsyncQueryExecutor`: ```csharp builder.Services.AddQuickGridEntityFrameworkAdapter(); diff --git a/aspnetcore/blazor/components/synchronization-context.md b/aspnetcore/blazor/components/synchronization-context.md index 36f341b8fc73..3affa3a0d9f5 100644 --- a/aspnetcore/blazor/components/synchronization-context.md +++ b/aspnetcore/blazor/components/synchronization-context.md @@ -12,7 +12,7 @@ uid: blazor/components/sync-context Blazor uses a synchronization context () to enforce a single logical thread of execution. A component's [lifecycle methods](xref:blazor/components/lifecycle) and event callbacks raised by Blazor are executed on the synchronization context. -Blazor Server's synchronization context attempts to emulate a single-threaded environment so that it closely matches the WebAssembly model in the browser, which is single threaded. At any given point in time, work is performed on exactly one thread, which yields the impression of a single logical thread. No two operations execute concurrently. +Blazor's server-side synchronization context attempts to emulate a single-threaded environment so that it closely matches the WebAssembly model in the browser, which is single threaded. At any given point in time, work is performed on exactly one thread, which yields the impression of a single logical thread. No two operations execute concurrently. ## Avoid thread-blocking calls diff --git a/aspnetcore/blazor/fundamentals/static-files.md b/aspnetcore/blazor/fundamentals/static-files.md index 22dc00f3679d..2939b99059d9 100644 --- a/aspnetcore/blazor/fundamentals/static-files.md +++ b/aspnetcore/blazor/fundamentals/static-files.md @@ -52,8 +52,15 @@ By default, publishing a Blazor WebAssembly app places the app's static assets, In the preceding example, the `{PATH}` placeholder is the path. +:::moniker range="< aspnetcore-8.0" + + + The `` property is most commonly used to control the paths to published static assets of multiple Blazor WebAssembly apps in a single hosted deployment. For more information, see . The property is also effective in standalone Blazor WebAssembly apps. +:::moniker-end + Without setting the `` property, the client app of a hosted solution or a standalone app is published at the following paths: * In the **:::no-loc text="Server":::** project of a hosted Blazor WebAssembly solution: `/BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/` @@ -126,5 +133,18 @@ To create additional file mappings with a + * [App base path](xref:blazor/host-and-deploy/index#app-base-path) * + +:::moniker-end diff --git a/aspnetcore/blazor/host-and-deploy/index.md b/aspnetcore/blazor/host-and-deploy/index.md index 0177776e9072..7746178453a6 100644 --- a/aspnetcore/blazor/host-and-deploy/index.md +++ b/aspnetcore/blazor/host-and-deploy/index.md @@ -157,8 +157,15 @@ If the app is a hosted Blazor WebAssembly app: `). * Configure the `` tag, per the guidance in the [Configure the app base path](#configure-the-app-base-path) section. +:::moniker range="< aspnetcore-8.0" + + + For an example of hosting multiple Blazor WebAssembly apps in a hosted Blazor WebAssembly solution, see , where approaches are explained for domain/port hosting and subpath hosting of multiple Blazor WebAssembly client apps. +:::moniker-end + ### Standalone Blazor WebAssembly In a standalone Blazor WebAssembly app, only the `` tag is configured, per the guidance in the [Configure the app base path](#configure-the-app-base-path) section. @@ -320,10 +327,17 @@ In scenarios where an app requires a separate area with custom resources and Raz app.Run(); ``` +:::moniker range="< aspnetcore-8.0" + + + ## Host multiple Blazor WebAssembly apps For more information on hosting multiple Blazor WebAssembly apps in a hosted Blazor [solution](xref:blazor/tooling#visual-studio-solution-file-sln), see . +:::moniker-end + ## Deployment For deployment guidance, see the following topics: diff --git a/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md b/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md index 471e8088e74e..0533dbe6a329 100644 --- a/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md +++ b/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md @@ -2,7 +2,7 @@ title: Multiple hosted ASP.NET Core Blazor WebAssembly apps author: guardrex description: Learn how to configure a hosted Blazor WebAssembly app to host multiple Blazor WebAssembly apps. -monikerRange: '>= aspnetcore-3.1' +monikerRange: '>= aspnetcore-3.1 < aspnetcore-8.0' ms.author: riande ms.custom: mvc ms.date: 05/12/2023 diff --git a/aspnetcore/blazor/host-and-deploy/webassembly.md b/aspnetcore/blazor/host-and-deploy/webassembly.md index a94719af8749..ccb6396677a2 100644 --- a/aspnetcore/blazor/host-and-deploy/webassembly.md +++ b/aspnetcore/blazor/host-and-deploy/webassembly.md @@ -21,10 +21,24 @@ With the [Blazor WebAssembly hosting model](xref:blazor/hosting-models#blazor-we The following deployment strategies are supported: +:::moniker range=">= aspnetcore-8.0" + +* The Blazor app is served by an ASP.NET Core app. This strategy is covered in the [Hosted deployment with ASP.NET Core](#hosted-deployment-with-aspnet-core) section. +* The Blazor app is placed on a static hosting web server or service, where .NET isn't used to serve the Blazor app. This strategy is covered in the [Standalone deployment](#standalone-deployment) section, which includes information on hosting a Blazor WebAssembly app as an IIS sub-app. + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + + + * The Blazor app is served by an ASP.NET Core app. This strategy is covered in the [Hosted deployment with ASP.NET Core](#hosted-deployment-with-aspnet-core) section. * The Blazor app is placed on a static hosting web server or service, where .NET isn't used to serve the Blazor app. This strategy is covered in the [Standalone deployment](#standalone-deployment) section, which includes information on hosting a Blazor WebAssembly app as an IIS sub-app. * An ASP.NET Core app hosts multiple Blazor WebAssembly apps. For more information, see . +:::moniker-end + :::moniker range=">= aspnetcore-8.0" ## Webcil packaging format for .NET assemblies @@ -279,10 +293,17 @@ For more information, see the following articles: * [.NET application publishing overview](/dotnet/core/deploying/) * +:::moniker range="< aspnetcore-8.0" + + + ## Hosted deployment with multiple Blazor WebAssembly apps For more information, see . +:::moniker-end + ## Standalone deployment A *standalone deployment* serves the Blazor WebAssembly app as a set of static files that are requested directly by clients. Any static file server is able to serve the Blazor app. From 393050350b115bb0cc241b254953e75e2b465b41 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Wed, 2 Aug 2023 10:42:13 -0400 Subject: [PATCH 05/11] Updates --- .../blazor/host-and-deploy/multiple-hosted-webassembly.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md b/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md index 0533dbe6a329..0b6bf744bf43 100644 --- a/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md +++ b/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md @@ -11,7 +11,12 @@ zone_pivot_groups: blazor-multiple-hosted-wasm-apps --- # Multiple hosted ASP.NET Core Blazor WebAssembly apps -[!INCLUDE[](~/includes/not-latest-version.md)] +:::moniker range="< aspnetcore-7.0" + +> [!NOTE] +> This isn't the latest version of this article. For the current release, see the [.NET 7 version of this article](?view=aspnetcore-7.0&preserve-view=true). + +:::moniker-end This article explains how to configure a hosted Blazor WebAssembly app to host multiple Blazor WebAssembly apps. From 3960bfc5b7d3483baffa60e36fdb4f39386f25c6 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Wed, 2 Aug 2023 10:46:03 -0400 Subject: [PATCH 06/11] Updates --- aspnetcore/blazor/components/class-libraries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/blazor/components/class-libraries.md b/aspnetcore/blazor/components/class-libraries.md index 3365ccbaf79f..94b951741e79 100644 --- a/aspnetcore/blazor/components/class-libraries.md +++ b/aspnetcore/blazor/components/class-libraries.md @@ -425,7 +425,7 @@ For more information, see -For more information, see . +For more information, see . :::moniker-end From 65a7c882c0a23077b3e3d5b3177c35e465e5a050 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Thu, 3 Aug 2023 15:57:36 -0400 Subject: [PATCH 07/11] Updates --- .../blazor/components/class-libraries.md | 7 ------- aspnetcore/blazor/components/css-isolation.md | 4 ---- aspnetcore/blazor/components/lifecycle.md | 8 +++---- .../blazor/fundamentals/static-files.md | 20 ------------------ aspnetcore/blazor/host-and-deploy/index.md | 14 ------------- .../multiple-hosted-webassembly.md | 2 +- .../blazor/host-and-deploy/webassembly.md | 21 ------------------- 7 files changed, 5 insertions(+), 71 deletions(-) diff --git a/aspnetcore/blazor/components/class-libraries.md b/aspnetcore/blazor/components/class-libraries.md index 94b951741e79..f4569e252529 100644 --- a/aspnetcore/blazor/components/class-libraries.md +++ b/aspnetcore/blazor/components/class-libraries.md @@ -418,17 +418,10 @@ For more information, see - For more information, see . -:::moniker-end - :::moniker range=">= aspnetcore-5.0" ## Client-side browser compatibility analyzer diff --git a/aspnetcore/blazor/components/css-isolation.md b/aspnetcore/blazor/components/css-isolation.md index adee0bf441fa..72cb8bb04a9b 100644 --- a/aspnetcore/blazor/components/css-isolation.md +++ b/aspnetcore/blazor/components/css-isolation.md @@ -57,16 +57,12 @@ CSS isolation occurs at build time. Blazor rewrites CSS selectors to match marku ``` -:::moniker range="< aspnetcore-8.0" - The following example is from a hosted Blazor WebAssembly **:::no-loc text="Client":::** app. The app's assembly name is `BlazorSample.Client`, and the `` is added by the Blazor WebAssembly project template when the project is created with the Hosted option (`-ho|--hosted` option using the .NET CLI or **ASP.NET Core Hosted** checkbox using Visual Studio): ```html ``` -:::moniker-end - Within the bundled file, each component is associated with a scope identifier. For each styled component, an HTML attribute is appended with the format `b-{STRING}`, where the `{STRING}` placeholder is a ten-character string generated by the framework. The identifier is unique for each app. In the rendered `Counter` component, Blazor appends a scope identifier to the `h1` element: ```html diff --git a/aspnetcore/blazor/components/lifecycle.md b/aspnetcore/blazor/components/lifecycle.md index 85e807b42554..d4c203cec232 100644 --- a/aspnetcore/blazor/components/lifecycle.md +++ b/aspnetcore/blazor/components/lifecycle.md @@ -157,13 +157,13 @@ Blazor apps that prerender their content on the server call -To prevent developer code in from running twice when prerendering, see the [Stateful reconnection after prerendering](#stateful-reconnection-after-prerendering) section. Although the content in the section focuses on Blazor Web Apps and stateful SignalR *reconnection*, the scenario for prerendering client-side rendered (CSR) WebAssembly components () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . +To prevent developer code in from running twice when prerendering, see the [Stateful reconnection after prerendering](#stateful-reconnection-after-prerendering) section. Although the content in the section focuses on Blazor Web Apps and stateful SignalR *reconnection*, the scenario for prerendering client-side rendered (CSR) WebAssembly components or client-side components in hosted Blazor WebAssembly solutions () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . :::moniker-end :::moniker range="< aspnetcore-8.0" -To prevent developer code in from running twice when prerendering, see the [Stateful reconnection after prerendering](#stateful-reconnection-after-prerendering) section. Although the content in the section focuses on Blazor Server and stateful SignalR *reconnection*, the scenario for prerendering in hosted Blazor WebAssembly apps () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . +To prevent developer code in from running twice when prerendering, see the [Stateful reconnection after prerendering](#stateful-reconnection-after-prerendering) section. Although the content in the section focuses on Blazor Server and stateful SignalR *reconnection*, the scenario for prerendering in hosted Blazor WebAssembly solutions () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . :::moniker-end @@ -389,13 +389,13 @@ For more information on the ) involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . +Although the content in this section focuses on Blazor Web Apps and stateful SignalR *reconnection*, the scenario for prerendering client-side rendered (CSR) WebAssembly components or client-side components in hosted Blazor WebAssembly solutions () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . :::moniker-end :::moniker range="< aspnetcore-8.0" -Although the content in this section focuses on Blazor Server and stateful SignalR *reconnection*, the scenario for prerendering in hosted Blazor WebAssembly apps () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . +Although the content in this section focuses on Blazor Server and stateful SignalR *reconnection*, the scenario for prerendering in hosted Blazor WebAssembly solutions () involves similar conditions and approaches to prevent executing developer code twice. To preserve state during the execution of initialization code while prerendering, see . :::moniker-end diff --git a/aspnetcore/blazor/fundamentals/static-files.md b/aspnetcore/blazor/fundamentals/static-files.md index 2939b99059d9..22dc00f3679d 100644 --- a/aspnetcore/blazor/fundamentals/static-files.md +++ b/aspnetcore/blazor/fundamentals/static-files.md @@ -52,15 +52,8 @@ By default, publishing a Blazor WebAssembly app places the app's static assets, In the preceding example, the `{PATH}` placeholder is the path. -:::moniker range="< aspnetcore-8.0" - - - The `` property is most commonly used to control the paths to published static assets of multiple Blazor WebAssembly apps in a single hosted deployment. For more information, see . The property is also effective in standalone Blazor WebAssembly apps. -:::moniker-end - Without setting the `` property, the client app of a hosted solution or a standalone app is published at the following paths: * In the **:::no-loc text="Server":::** project of a hosted Blazor WebAssembly solution: `/BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/` @@ -133,18 +126,5 @@ To create additional file mappings with a - * [App base path](xref:blazor/host-and-deploy/index#app-base-path) * - -:::moniker-end diff --git a/aspnetcore/blazor/host-and-deploy/index.md b/aspnetcore/blazor/host-and-deploy/index.md index 7746178453a6..0177776e9072 100644 --- a/aspnetcore/blazor/host-and-deploy/index.md +++ b/aspnetcore/blazor/host-and-deploy/index.md @@ -157,15 +157,8 @@ If the app is a hosted Blazor WebAssembly app: `). * Configure the `` tag, per the guidance in the [Configure the app base path](#configure-the-app-base-path) section. -:::moniker range="< aspnetcore-8.0" - - - For an example of hosting multiple Blazor WebAssembly apps in a hosted Blazor WebAssembly solution, see , where approaches are explained for domain/port hosting and subpath hosting of multiple Blazor WebAssembly client apps. -:::moniker-end - ### Standalone Blazor WebAssembly In a standalone Blazor WebAssembly app, only the `` tag is configured, per the guidance in the [Configure the app base path](#configure-the-app-base-path) section. @@ -327,17 +320,10 @@ In scenarios where an app requires a separate area with custom resources and Raz app.Run(); ``` -:::moniker range="< aspnetcore-8.0" - - - ## Host multiple Blazor WebAssembly apps For more information on hosting multiple Blazor WebAssembly apps in a hosted Blazor [solution](xref:blazor/tooling#visual-studio-solution-file-sln), see . -:::moniker-end - ## Deployment For deployment guidance, see the following topics: diff --git a/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md b/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md index 0b6bf744bf43..1e3e6beff1e3 100644 --- a/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md +++ b/aspnetcore/blazor/host-and-deploy/multiple-hosted-webassembly.md @@ -2,7 +2,7 @@ title: Multiple hosted ASP.NET Core Blazor WebAssembly apps author: guardrex description: Learn how to configure a hosted Blazor WebAssembly app to host multiple Blazor WebAssembly apps. -monikerRange: '>= aspnetcore-3.1 < aspnetcore-8.0' +monikerRange: '>= aspnetcore-3.1' ms.author: riande ms.custom: mvc ms.date: 05/12/2023 diff --git a/aspnetcore/blazor/host-and-deploy/webassembly.md b/aspnetcore/blazor/host-and-deploy/webassembly.md index ccb6396677a2..a94719af8749 100644 --- a/aspnetcore/blazor/host-and-deploy/webassembly.md +++ b/aspnetcore/blazor/host-and-deploy/webassembly.md @@ -21,24 +21,10 @@ With the [Blazor WebAssembly hosting model](xref:blazor/hosting-models#blazor-we The following deployment strategies are supported: -:::moniker range=">= aspnetcore-8.0" - -* The Blazor app is served by an ASP.NET Core app. This strategy is covered in the [Hosted deployment with ASP.NET Core](#hosted-deployment-with-aspnet-core) section. -* The Blazor app is placed on a static hosting web server or service, where .NET isn't used to serve the Blazor app. This strategy is covered in the [Standalone deployment](#standalone-deployment) section, which includes information on hosting a Blazor WebAssembly app as an IIS sub-app. - -:::moniker-end - -:::moniker range="< aspnetcore-8.0" - - - * The Blazor app is served by an ASP.NET Core app. This strategy is covered in the [Hosted deployment with ASP.NET Core](#hosted-deployment-with-aspnet-core) section. * The Blazor app is placed on a static hosting web server or service, where .NET isn't used to serve the Blazor app. This strategy is covered in the [Standalone deployment](#standalone-deployment) section, which includes information on hosting a Blazor WebAssembly app as an IIS sub-app. * An ASP.NET Core app hosts multiple Blazor WebAssembly apps. For more information, see . -:::moniker-end - :::moniker range=">= aspnetcore-8.0" ## Webcil packaging format for .NET assemblies @@ -293,17 +279,10 @@ For more information, see the following articles: * [.NET application publishing overview](/dotnet/core/deploying/) * -:::moniker range="< aspnetcore-8.0" - - - ## Hosted deployment with multiple Blazor WebAssembly apps For more information, see . -:::moniker-end - ## Standalone deployment A *standalone deployment* serves the Blazor WebAssembly app as a set of static files that are requested directly by clients. Any static file server is able to serve the Blazor app. From 912bd9fbf3709f9ac91e8903ffc8dead7e76d719 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 7 Aug 2023 09:08:47 -0400 Subject: [PATCH 08/11] Updates --- .../blazor/components/built-in-components.md | 2 + .../cascading-values-and-parameters.md | 12 +- .../blazor/components/class-libraries.md | 8 +- .../blazor/components/control-head-content.md | 2 +- aspnetcore/blazor/components/css-isolation.md | 51 +++++- aspnetcore/blazor/components/data-binding.md | 32 ++-- .../blazor/components/dynamiccomponent.md | 54 +++--- .../element-component-model-relationships.md | 4 +- .../blazor/components/event-handling.md | 22 +-- .../blazor/components/generic-type-support.md | 26 +-- aspnetcore/blazor/components/index.md | 169 ++++++++++++++---- .../blazor/components/js-spa-frameworks.md | 30 ++-- aspnetcore/blazor/components/layouts.md | 16 +- aspnetcore/blazor/components/lifecycle.md | 16 +- .../components/overwriting-parameters.md | 6 +- aspnetcore/blazor/components/quickgrid.md | 4 +- ...render-components-outside-of-aspnetcore.md | 4 +- aspnetcore/blazor/components/rendering.md | 17 +- aspnetcore/blazor/components/sections.md | 8 +- ...lat-attributes-and-arbitrary-parameters.md | 10 +- .../components/synchronization-context.md | 2 +- .../blazor/components/templated-components.md | 10 +- .../blazor/components/virtualization.md | 2 +- 23 files changed, 320 insertions(+), 187 deletions(-) diff --git a/aspnetcore/blazor/components/built-in-components.md b/aspnetcore/blazor/components/built-in-components.md index 519699c96e6d..6fa6d9d26858 100644 --- a/aspnetcore/blazor/components/built-in-components.md +++ b/aspnetcore/blazor/components/built-in-components.md @@ -16,6 +16,8 @@ The following built-in Razor components are provided by the Blazor framework: :::moniker range=">= aspnetcore-8.0" + + * [`App`](xref:blazor/project-structure) * [`Authentication`](xref:blazor/security/webassembly/index#authentication-component) * [`AuthorizeView`](xref:blazor/security/index#authorizeview-component) diff --git a/aspnetcore/blazor/components/cascading-values-and-parameters.md b/aspnetcore/blazor/components/cascading-values-and-parameters.md index e38faeba6256..26727e042e96 100644 --- a/aspnetcore/blazor/components/cascading-values-and-parameters.md +++ b/aspnetcore/blazor/components/cascading-values-and-parameters.md @@ -58,7 +58,7 @@ The following `ThemeInfo` C# class is placed in a folder named `UIThemeClasses` The following [layout component](xref:blazor/components/layouts) specifies theme information (`ThemeInfo`) as a cascading value for all components that make up the layout body of the property. `ButtonClass` is assigned a value of [`btn-success`](https://getbootstrap.com/docs/5.0/components/buttons/), which is a Bootstrap button style. Any descendent component in the component hierarchy can use the `ButtonClass` property through the `ThemeInfo` cascading value. -`Shared/MainLayout.razor`: +`MainLayout.razor`: :::moniker range=">= aspnetcore-7.0" @@ -90,7 +90,7 @@ To make use of cascading values, descendent components declare cascading paramet The following component binds the `ThemeInfo` cascading value to a cascading parameter, optionally using the same name of `ThemeInfo`. The parameter is used to set the CSS class for the **`Increment Counter (Themed)`** button. -`Pages/ThemedCounter.razor`: +`ThemedCounter.razor`: :::moniker range=">= aspnetcore-7.0" @@ -120,7 +120,7 @@ The following component binds the `ThemeInfo` cascading value to a cascading par Similar to a regular component parameter, components accepting a cascading parameter are rerendered when the cascading value is changed. For instance, configuring a different theme instance causes the `ThemedCounter` component from the [`CascadingValue` component](#cascadingvalue-component) section to rerender: -`Shared/MainLayout.razor`: +`MainLayout.razor`: ```razor
@@ -212,7 +212,7 @@ The following `TabSet` component maintains a set of tabs. The tab set's `Tab` co Child `Tab` components aren't explicitly passed as parameters to the `TabSet`. Instead, the child `Tab` components are part of the child content of the `TabSet`. However, the `TabSet` still needs a reference each `Tab` component so that it can render the headers and the active tab. To enable this coordination without requiring additional code, the `TabSet` component *can provide itself as a cascading value* that is then picked up by the descendent `Tab` components. -`Shared/TabSet.razor`: +`TabSet.razor`: ```razor @using BlazorSample.UIInterfaces @@ -258,7 +258,7 @@ Child `Tab` components aren't explicitly passed as parameters to the `TabSet`. I Descendent `Tab` components capture the containing `TabSet` as a cascading parameter. The `Tab` components add themselves to the `TabSet` and coordinate to set the active tab. -`Shared/Tab.razor`: +`Tab.razor`: ```razor @using BlazorSample.UIInterfaces @@ -297,7 +297,7 @@ Descendent `Tab` components capture the containing `TabSet` as a cascading param The following `ExampleTabSet` component uses the `TabSet` component, which contains three `Tab` components. -`Pages/ExampleTabSet.razor`: +`ExampleTabSet.razor`: ```razor @page "/example-tab-set" diff --git a/aspnetcore/blazor/components/class-libraries.md b/aspnetcore/blazor/components/class-libraries.md index f4569e252529..c0671c6bd67d 100644 --- a/aspnetcore/blazor/components/class-libraries.md +++ b/aspnetcore/blazor/components/class-libraries.md @@ -188,7 +188,7 @@ In the following examples, `ComponentLibrary` is an RCL containing the `Componen In the app that consumes the RCL, reference the `Component1` component using its namespace, as the following example shows. -`Pages/ConsumeComponent1.razor`: +`ConsumeComponent1.razor`: ```razor @page "/consume-component-1" @@ -200,7 +200,7 @@ In the app that consumes the RCL, reference the `Component1` component using its Alternatively, add a [`@using`](xref:mvc/views/razor#using) directive and use the component without its namespace. The following `@using` directive can also appear in any `_Imports.razor` file in or above the current folder. -`Pages/ConsumeComponent2.razor`: +`ConsumeComponent2.razor`: ```razor @page "/consume-component-2" @@ -276,7 +276,7 @@ Add a component to the RCL that uses the `extra-style` class. Add a page to the app that uses the `ExtraStyles` component from the RCL. -`Pages/ConsumeComponent3.razor`: +`ConsumeComponent3.razor`: ```razor @page "/consume-component-3" @@ -382,7 +382,7 @@ Add the following `Jeep` component to the app that consumes the `ComponentLibrar * The Jeep YJ® image from the `ComponentLibrary` RCL's `wwwroot` folder. * The `JeepYJ` component from the RCL. -`Pages/Jeep.razor`: +`Jeep.razor`: ```razor @page "/jeep" diff --git a/aspnetcore/blazor/components/control-head-content.md b/aspnetcore/blazor/components/control-head-content.md index 88c6fabeb032..715514a9bf8c 100644 --- a/aspnetcore/blazor/components/control-head-content.md +++ b/aspnetcore/blazor/components/control-head-content.md @@ -22,7 +22,7 @@ Specify `` element content with the Scoped CSS Example ``` -`Pages/Example.razor.css`: +`Example.razor.css`: ```css h1 { @@ -72,7 +72,7 @@ Within the bundled file, each component is associated with a scope identifier. F The `{ASSEMBLY NAME}.styles.css` file uses the scope identifier to group a style declaration with its component. The following example provides the style for the preceding `

` element: ```css -/* /Pages/Counter.razor.rz.scp.css */ +/* /Components/Pages/Counter.razor.rz.scp.css */ h1[b-3xxtam6d07] { color: brown; } @@ -90,7 +90,7 @@ By default, CSS isolation only applies to the component you associate with the f The following example shows a parent component called `Parent` with a child component called `Child`. -`Pages/Parent.razor`: +`Parent.razor`: ```razor @page "/parent" @@ -102,7 +102,7 @@ The following example shows a parent component called `Parent` with a child comp

``` -`Shared/Child.razor`: +`Child.razor`: ```razor

Child Component

@@ -110,7 +110,7 @@ The following example shows a parent component called `Parent` with a child comp Update the `h1` declaration in `Parent.razor.css` with the `::deep` pseudo-element to signify the `h1` style declaration must apply to the parent component and its children. -`Pages/Parent.razor.css`: +`Parent.razor.css`: ```css ::deep h1 { @@ -122,7 +122,7 @@ The `h1` style now applies to the `Parent` and `Child` components without the ne The `::deep` pseudo-element only works with descendant elements. The following markup applies the `h1` styles to components as expected. The parent component's scope identifier is applied to the `div` element, so the browser knows to inherit styles from the parent component. -`Pages/Parent.razor`: +`Parent.razor`: ```razor
@@ -134,7 +134,7 @@ The `::deep` pseudo-element only works with descendant elements. The following m However, excluding the `div` element removes the descendant relationship. In the following example, the style is **not** applied to the child component. -`Pages/Parent.razor`: +`Parent.razor`: ```razor

Parent

@@ -161,6 +161,39 @@ CSS isolation is designed to work out-of-the-box but provides configuration for ### Customize scope identifier format +:::moniker range=">= aspnetcore-8.0" + +By default, scope identifiers use the format `b-{STRING}`, where the `{STRING}` placeholder is a ten-character string generated by the framework. To customize the scope identifier format, update the project file to a desired pattern: + +```xml + + + +``` + +In the preceding example, the CSS generated for `Example.razor.css` changes its scope identifier from `b-{STRING}` to `custom-scope-identifier`. + +Use scope identifiers to achieve inheritance with scoped CSS files. In the following project file example, a `BaseComponent.razor.css` file contains common styles across components. A `DerivedComponent.razor.css` file inherits these styles. + +```xml + + + + +``` + +Use the wildcard (`*`) operator to share scope identifiers across multiple files: + +```xml + + + +``` + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + By default, scope identifiers use the format `b-{STRING}`, where the `{STRING}` placeholder is a ten-character string generated by the framework. To customize the scope identifier format, update the project file to a desired pattern: ```xml @@ -188,6 +221,8 @@ Use the wildcard (`*`) operator to share scope identifiers across multiple files ``` +:::moniker-end + ### Change base path for static web assets The `scoped.styles.css` file is generated at the root of the app. In the project file, use the [`` property](xref:blazor/fundamentals/static-files#static-web-asset-base-path) to change the default path. The following example places the `scoped.styles.css` file, and the rest of the app's assets, at the `_content` path: diff --git a/aspnetcore/blazor/components/data-binding.md b/aspnetcore/blazor/components/data-binding.md index 72c7a823a925..7473c49fc8fe 100644 --- a/aspnetcore/blazor/components/data-binding.md +++ b/aspnetcore/blazor/components/data-binding.md @@ -23,7 +23,7 @@ The following example binds: When an `` element loses focus, its bound field or property is updated. -`Pages/Bind.razor`: +`Bind.razor`: :::moniker range=">= aspnetcore-7.0" @@ -53,7 +53,7 @@ The text box is updated in the UI only when the component is rendered, not in re As a demonstration of how data binding composes in HTML, the following example binds the `InputValue` property to the second `` element's `value` and `onchange` attributes ([`change`](https://developer.mozilla.org/docs/Web/API/HTMLElement/change_event)). *The second `` element in the following example is a concept demonstration and isn't meant to suggest how you should bind data in Razor components.* -`Pages/BindTheory.razor`: +`BindTheory.razor`: :::moniker range=">= aspnetcore-7.0" @@ -148,7 +148,7 @@ In the following example: Additional examples -`Pages/BindAfter.razor`: +`BindAfter.razor`: ```razor @page "/bind-after" @@ -193,7 +193,7 @@ Using an event callback parameter with `@bind:set` (`[Parameter] public EventCal Examples -`Pages/BindGetSet.razor`: +`BindGetSet.razor`: ```razor @page "/bind-get-set" @@ -300,7 +300,7 @@ Using `@bind:get`/`@bind:set` modifiers both controls the underlying value of `i [C# `get` and `set` accessors](/dotnet/csharp/programming-guide/classes-and-structs/using-properties) can be used to create custom binding format behavior, as the following `DecimalBinding` component demonstrates. The component binds a positive or negative decimal with up to three decimal places to an `` element by way of a `string` property (`DecimalValue`). -`Pages/DecimalBinding.razor`: +`DecimalBinding.razor`: :::moniker range=">= aspnetcore-7.0" @@ -346,7 +346,7 @@ Using `@bind:get`/`@bind:set` modifiers both controls the underlying value of `i Binding supports [`multiple`](https://developer.mozilla.org/docs/Web/HTML/Attributes/multiple) option selection with `` element is bound to an `int` type with an initial value of `123`. -`Pages/UnparsableValues.razor`: +`UnparsableValues.razor`: :::moniker range=">= aspnetcore-7.0" @@ -465,7 +465,7 @@ For the `oninput` event (`@bind:event="oninput"`), a value reversion occurs afte Data binding works with a single format string using `@bind:format="{FORMAT STRING}"`, where the `{FORMAT STRING}` placeholder is the format string. Other format expressions, such as currency or number formats, aren't available at this time but might be added in a future release. -`Pages/DateBinding.razor`: +`DateBinding.razor`: :::moniker range=">= aspnetcore-7.0" @@ -524,7 +524,7 @@ The following `ChildBind` component has a `Year` component parameter and an invokes the delegate associated with the binding with the provided argument and dispatches an event notification for the changed property. -`Shared/ChildBind.razor`: +`ChildBind.razor`: :::moniker range=">= aspnetcore-7.0" @@ -554,7 +554,7 @@ For more information on events and . -`Shared/PasswordEntry.razor`: +`PasswordEntry.razor`: :::moniker range=">= aspnetcore-7.0" @@ -639,7 +639,7 @@ In a more sophisticated and real-world example, the following `PasswordEntry` co The `PasswordEntry` component is used in another component, such as the following `PasswordBinding` component example. -`Pages/PasswordBinding.razor`: +`PasswordBinding.razor`: :::moniker range=">= aspnetcore-7.0" @@ -672,7 +672,7 @@ When the `PasswordBinding` component is initially rendered, the `password` value Perform checks or trap errors in the handler. The following revised `PasswordEntry` component provides immediate feedback to the user if a space is used in the password's value. -`Shared/PasswordEntry.razor`: +`PasswordEntry.razor`: :::moniker range=">= aspnetcore-7.0" @@ -713,7 +713,7 @@ You can bind parameters through any number of nested components, but you must re A common and recommended approach is to only store the underlying data in the parent component to avoid any confusion about what state must be updated, as shown in the following example. -`Pages/Parent2.razor`: +`Parent2.razor`: :::moniker range=">= aspnetcore-7.0" @@ -748,7 +748,7 @@ In the following `NestedChild` component, the `NestedGrandchild` component: :::moniker-end -`Shared/NestedChild.razor`: +`NestedChild.razor`: :::moniker range=">= aspnetcore-7.0" @@ -781,7 +781,7 @@ In the following `NestedChild` component, the `NestedGrandchild` component: :::moniker-end -`Shared/NestedGrandchild.razor`: +`NestedGrandchild.razor`: :::moniker range=">= aspnetcore-7.0" diff --git a/aspnetcore/blazor/components/dynamiccomponent.md b/aspnetcore/blazor/components/dynamiccomponent.md index d52574315b7f..7917943e3084 100644 --- a/aspnetcore/blazor/components/dynamiccomponent.md +++ b/aspnetcore/blazor/components/dynamiccomponent.md @@ -62,30 +62,30 @@ In the following example, a Razor component renders a component based on the use | User spaceflight carrier selection | Shared Razor component to render | | ---------------------------------- | ----------------------------------- | -| Rocket Lab® | `Shared/RocketLab.razor` | -| SpaceX® | `Shared/SpaceX.razor` | -| ULA® | `Shared/UnitedLaunchAlliance.razor` | -| Virgin Galactic® | `Shared/VirginGalactic.razor` | +| Rocket Lab® | `RocketLab.razor` | +| SpaceX® | `SpaceX.razor` | +| ULA® | `UnitedLaunchAlliance.razor` | +| Virgin Galactic® | `VirginGalactic.razor` | :::moniker range=">= aspnetcore-7.0" -`Shared/RocketLab.razor`: +`RocketLab.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/RocketLab.razor"::: -`Shared/SpaceX.razor`: +`SpaceX.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/SpaceX.razor"::: -`Shared/UnitedLaunchAlliance.razor`: +`UnitedLaunchAlliance.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/UnitedLaunchAlliance.razor"::: -`Shared/VirginGalactic.razor`: +`VirginGalactic.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/VirginGalactic.razor"::: -`Pages/DynamicComponentExample1.razor`: +`DynamicComponentExample1.razor`: :::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/dynamiccomponent/DynamicComponentExample1.razor"::: @@ -93,23 +93,23 @@ In the following example, a Razor component renders a component based on the use :::moniker range="< aspnetcore-7.0" -`Shared/RocketLab.razor`: +`RocketLab.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/RocketLab.razor"::: -`Shared/SpaceX.razor`: +`SpaceX.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/SpaceX.razor"::: -`Shared/UnitedLaunchAlliance.razor`: +`UnitedLaunchAlliance.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/UnitedLaunchAlliance.razor"::: -`Shared/VirginGalactic.razor`: +`VirginGalactic.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Shared/dynamiccomponent/VirginGalactic.razor"::: -`Pages/DynamicComponentExample1.razor`: +`DynamicComponentExample1.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/dynamiccomponent/DynamicComponentExample1.razor"::: @@ -140,9 +140,9 @@ The following example configures a component metadata object (`ComponentMetadata :::moniker-end -The following `RocketLabWithWindowSeat` component (`Shared/RocketLabWithWindowSeat.razor`) has been updated from the preceding example to include a component parameter named `WindowSeat` to specify if the passenger prefers a window seat on their flight: +The following `RocketLabWithWindowSeat` component (`RocketLabWithWindowSeat.razor`) has been updated from the preceding example to include a component parameter named `WindowSeat` to specify if the passenger prefers a window seat on their flight: -`Shared/RocketLabWithWindowSeat.razor`: +`RocketLabWithWindowSeat.razor`: :::moniker range=">= aspnetcore-7.0" @@ -160,14 +160,14 @@ In the following example: * Only the `RocketLabWithWindowSeat` component's parameter for a window seat (`WindowSeat`) receives the value of the **`Window Seat`** checkbox. * The namespace of the app is `BlazorSample`. ***Change the namespace to match your app's namespace.*** -* The dynamically-rendered components are shared components in the app's `Shared` folder: - * Shown in this article section: `RocketLabWithWindowSeat` (`Shared/RocketLabWithWindowSeat.razor`) +* The dynamically-rendered components are shared components: + * Shown in this article section: `RocketLabWithWindowSeat` (`RocketLabWithWindowSeat.razor`) * Components shown in the [Example](#example) section earlier in this article: - * `SpaceX` (`Shared/SpaceX.razor`) - * `UnitedLaunchAlliance` (`Shared/UnitedLaunchAlliance.razor`) - * `VirginGalactic` (`Shared/VirginGalactic.razor`) + * `SpaceX` (`SpaceX.razor`) + * `UnitedLaunchAlliance` (`UnitedLaunchAlliance.razor`) + * `VirginGalactic` (`VirginGalactic.razor`) -`Pages/DynamicComponentExample2.razor`: +`DynamicComponentExample2.razor`: :::moniker range=">= aspnetcore-7.0" @@ -201,7 +201,7 @@ Event callbacks () can be pa Implement an event callback parameter () within each dynamically-rendered component. -`Shared/RocketLab2.razor`: +`RocketLab2.razor`: :::moniker range=">= aspnetcore-7.0" @@ -215,7 +215,7 @@ Implement an event callback parameter ( [!IMPORTANT] > For the following `DynamicComponentExample3` component, modify the code in the `OnDropdownChange` method. Change the namespace name of "`BlazorSample`" in the `Type.GetType()` argument to match your app's namespace. -`Pages/DynamicComponentExample3.razor`: +`DynamicComponentExample3.razor`: :::moniker range=">= aspnetcore-7.0" diff --git a/aspnetcore/blazor/components/element-component-model-relationships.md b/aspnetcore/blazor/components/element-component-model-relationships.md index efac30ab23c7..bd84437a62b4 100644 --- a/aspnetcore/blazor/components/element-component-model-relationships.md +++ b/aspnetcore/blazor/components/element-component-model-relationships.md @@ -24,7 +24,7 @@ This demonstration allows you to: * Select an `` from among several rendered `Details` components. * Study the behavior of the page's focus as the people collection automatically grows. -`Shared/Details.razor`: +`Details.razor`: :::moniker range=">= aspnetcore-7.0" @@ -52,7 +52,7 @@ This demonstration allows you to: In the following `PeopleExample` component, each iteration of adding a person in `OnTimerCallback` results in Blazor rebuilding the entire collection. The page's focus remains on the *same index* position of `` elements, so the focus shifts each time a person is added. *Shifting the focus away from what the user selected isn't desirable behavior.* After demonstrating the poor behavior with the following component, the [`@key`](xref:mvc/views/razor#key) directive attribute is used to improve the user's experience. -`Pages/PeopleExample.razor`: +`PeopleExample.razor`: :::moniker range=">= aspnetcore-7.0" diff --git a/aspnetcore/blazor/components/event-handling.md b/aspnetcore/blazor/components/event-handling.md index d83fa804edc9..c00057c5533b 100644 --- a/aspnetcore/blazor/components/event-handling.md +++ b/aspnetcore/blazor/components/event-handling.md @@ -30,7 +30,7 @@ The following code: * Calls the `UpdateHeading` method when the button is selected in the UI. * Calls the `CheckChanged` method when the checkbox is changed in the UI. -`Pages/EventHandlerExample1.razor`: +`EventHandlerExample1.razor`: :::moniker range=">= aspnetcore-7.0" @@ -61,7 +61,7 @@ In the following example, `UpdateHeading`: * Is called asynchronously when the button is selected. * Waits two seconds before updating the heading. -`Pages/EventHandlerExample2.razor`: +`EventHandlerExample2.razor`: :::moniker range=">= aspnetcore-7.0" @@ -91,7 +91,7 @@ In the following example, `UpdateHeading`: For events that support an event argument type, specifying an event parameter in the event method definition is only necessary if the event type is used in the method. In the following example, is used in the `ReportPointerLocation` method to set message text that reports the mouse coordinates when the user selects a button in the UI. -`Pages/EventHandlerExample3.razor`: +`EventHandlerExample3.razor`: :::moniker range=">= aspnetcore-7.0" @@ -300,7 +300,7 @@ Event name conventions differ between .NET and JavaScript: In a Razor component, attach the custom handler to an element. -`Pages/CustomPasteArguments.razor`: +`CustomPasteArguments.razor`: ```razor @page "/custom-paste-arguments" @@ -332,7 +332,7 @@ In a Razor component, attach the custom handler to an element. [Lambda expressions](/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions) are supported as the delegate event handler. -`Pages/EventHandlerExample4.razor`: +`EventHandlerExample4.razor`: :::moniker range=">= aspnetcore-7.0" @@ -363,7 +363,7 @@ It's often convenient to close over additional values using C# method parameters * An event argument () in `e`. * The button number in `buttonNumber`. -`Pages/EventHandlerExample5.razor`: +`EventHandlerExample5.razor`: :::moniker range=">= aspnetcore-7.0" @@ -415,7 +415,7 @@ A common scenario with nested components executes a parent component's method wh The following `Child` component demonstrates how a button's `onclick` handler is set up to receive an delegate from the sample's `ParentComponent`. The is typed with `MouseEventArgs`, which is appropriate for an `onclick` event from a peripheral device. -`Shared/Child.razor`: +`Child.razor`: :::moniker range=">= aspnetcore-7.0" @@ -443,7 +443,7 @@ The following `Child` component demonstrates how a button's `onclick` handler is The `Parent` component sets the child's (`OnClickCallback`) to its `ShowMessage` method. -`Pages/Parent.razor`: +`Parent.razor`: :::moniker range=">= aspnetcore-7.0" @@ -497,7 +497,7 @@ Use the [`@on{DOM EVENT}:preventDefault`](xref:mvc/views/razor#oneventpreventdef When a key is selected on an input device and the element focus is on a text box, a browser normally displays the key's character in the text box. In the following example, the default behavior is prevented by specifying the `@onkeydown:preventDefault` directive attribute. When the focus is on the `` element, the counter increments with the key sequence Shift++. The `+` character isn't assigned to the `` element's value. For more information on `keydown`, see [`MDN Web Docs: Document: keydown` event](https://developer.mozilla.org/docs/Web/API/Document/keydown_event). -`Pages/EventHandlerExample6.razor`: +`EventHandlerExample6.razor`: :::moniker range=">= aspnetcore-7.0" @@ -548,7 +548,7 @@ The `stopPropagation` directive attribute's effect is limited to the Blazor scop In the following example, selecting the checkbox prevents click events from the second child `
` from propagating to the parent `
`. Since propagated click events normally fire the `OnSelectParentDiv` method, selecting the second child `
` results in the parent `
` message appearing unless the checkbox is selected. -`Pages/EventHandlerExample7.razor`: +`EventHandlerExample7.razor`: :::moniker range=">= aspnetcore-7.0" @@ -580,7 +580,7 @@ In the following example, selecting the checkbox prevents click events from the Call on an [element reference](xref:blazor/js-interop/call-javascript-from-dotnet#capture-references-to-elements) to focus an element in code. In the following example, select the button to focus the `` element. -`Pages/EventHandlerExample8.razor`: +`EventHandlerExample8.razor`: :::moniker-end diff --git a/aspnetcore/blazor/components/generic-type-support.md b/aspnetcore/blazor/components/generic-type-support.md index 6cb2bd2350e1..7398a339c56c 100644 --- a/aspnetcore/blazor/components/generic-type-support.md +++ b/aspnetcore/blazor/components/generic-type-support.md @@ -30,7 +30,7 @@ C# syntax with [`where`](/dotnet/csharp/language-reference/keywords/where-generi In the following example, the `ListGenericTypeItems1` component is generically typed as `TExample`. -`Shared/ListGenericTypeItems1.razor`: +`ListGenericTypeItems1.razor`: :::moniker range=">= aspnetcore-7.0" @@ -61,7 +61,7 @@ The following `GenericTypeExample1` component renders two `ListGenericTypeItems1 * String or integer data is assigned to the `ExampleList` parameter of each component. * Type `string` or `int` that matches the type of the assigned data is set for the type parameter (`TExample`) of each component. -`Pages/GenericTypeExample1.razor`: +`GenericTypeExample1.razor`: :::moniker range=">= aspnetcore-7.0" @@ -112,7 +112,7 @@ Generic types can be cascaded to child components in either of the following app The following subsections provide examples of the preceding approaches using the following two `ListDisplay` components. The components receive and render list data and are generically typed as `TExample`. These components are for demonstration purposes and only differ in the color of text that the list is rendered. If you wish to experiment with the components in the following sub-sections in a local test app, add the following two components to the app first. -`Shared/ListDisplay1.razor`: +`ListDisplay1.razor`: ```razor @typeparam TExample @@ -133,7 +133,7 @@ The following subsections provide examples of the preceding approaches using the } ``` -`Shared/ListDisplay2.razor`: +`ListDisplay2.razor`: ```razor @typeparam TExample @@ -163,7 +163,7 @@ The demonstration in this section cascades a type explicitly for `TExample`. The following `ListGenericTypeItems2` component receives data and cascades a generic type parameter named `TExample` to its descendent components. In the upcoming parent component, the `ListGenericTypeItems2` component is used to display list data with the preceding `ListDisplay` component. -`Shared/ListGenericTypeItems2.razor`: +`ListGenericTypeItems2.razor`: ```razor @attribute [CascadingTypeParameter(nameof(TExample))] @@ -181,7 +181,7 @@ The following `ListGenericTypeItems2` component receives data and cascades a gen The following `GenericTypeExample2` parent component sets the child content () of two `ListGenericTypeItems2` components specifying the `ListGenericTypeItems2` types (`TExample`), which are cascaded to child components. `ListDisplay` components are rendered with the list item data shown in the example. String data is used with the first `ListGenericTypeItems2` component, and integer data is used with the second `ListGenericTypeItems2` component. -`Pages/GenericTypeExample2.razor`: +`GenericTypeExample2.razor`: ```razor @page "/generic-type-example-2" @@ -201,7 +201,7 @@ The following `GenericTypeExample2` parent component sets the child content ( [!NOTE] > This section uses the two `ListDisplay` components in the [Cascaded generic type support](#cascaded-generic-type-support) section. -`Shared/ListGenericTypeItems4.razor`: +`ListGenericTypeItems4.razor`: ```razor @attribute [CascadingTypeParameter(nameof(TExample))] @@ -359,7 +359,7 @@ The demonstration in this section cascades a type inferred for `TExample`. The following `GenericTypeExample4` component with inferred cascaded types provides different data for display. -`Pages/GenericTypeExample4.razor`: +`GenericTypeExample4.razor`: ```razor @page "/generic-type-example-4" @@ -379,7 +379,7 @@ The following `GenericTypeExample4` component with inferred cascaded types provi The following `GenericTypeExample5` component with inferred cascaded types provides the same data for display. The following example directly assigns the data to the components. -`Pages/GenericTypeExample5.razor`: +`GenericTypeExample5.razor`: ```razor @page "/generic-type-example-5" diff --git a/aspnetcore/blazor/components/index.md b/aspnetcore/blazor/components/index.md index 70bb28fc1db9..36d9e72598a0 100644 --- a/aspnetcore/blazor/components/index.md +++ b/aspnetcore/blazor/components/index.md @@ -14,7 +14,7 @@ uid: blazor/components/index This article explains how to create and use Razor components in Blazor apps, including guidance on Razor syntax, component naming, namespaces, and component parameters. -Blazor apps are built using *Razor components*, informally known as *Blazor components*. A component is a self-contained portion of user interface (UI) with processing logic to enable dynamic behavior. Components can be nested, reused, shared among projects, and [used in MVC and Razor Pages apps](xref:blazor/components/prerendering-and-integration). +Blazor apps are built using *Razor components*, informally known as *Blazor components* or only *components*. A component is a self-contained portion of user interface (UI) with processing logic to enable dynamic behavior. Components can be nested, reused, shared among projects, and [used in MVC and Razor Pages apps](xref:blazor/components/prerendering-and-integration). ## Component classes @@ -39,6 +39,69 @@ Directives and directive attributes used in components are explained further in ### Component name, class name, and namespace +:::moniker range=">= aspnetcore-8.0" + +A component's name must start with an uppercase character: + +Supported: `ProductDetail.razor` + +Unsupported: `productDetail.razor` + +Common Blazor naming conventions used throughout the Blazor documentation include: + +* File paths and file names use Pascal case† and appear before showing code examples. If a path is present, it indicates the typical folder location. For example, `Components/Pages/ProductDetail.razor` indicates that the `ProductDetail` component has a file name of `ProductDetail.razor` and resides in the `Pages` folder of the `Components` folder of the app. +* Component file paths for routable components match their URLs in kebab case‡ with hyphens appearing between words in a component's route template. For example, a `ProductDetail` component with a route template of `/product-detail` (`@page "/product-detail"`) is requested in a browser at the relative URL `/product-detail`. + +†Pascal case (upper camel case) is a naming convention without spaces and punctuation and with the first letter of each word capitalized, including the first word. +‡Kebab case is a naming convention without spaces and punctuation that uses lowercase letters and dashes between words. + +Components are ordinary [C# classes](/dotnet/csharp/programming-guide/classes-and-structs/classes) and can be placed anywhere within a project. Components that produce webpages usually reside in the `Components/Pages` folder. Non-page components are frequently placed in the `Components` folder or a custom folder added to the project. + +Typically, a component's namespace is derived from the app's root namespace and the component's location (folder) within the app. If the app's root namespace is `BlazorSample` and the `Counter` component resides in the `Components/Pages` folder: + +* The `Counter` component's namespace is `BlazorSample.Components.Pages`. +* The fully qualified type name of the component is `BlazorSample.Components.Pages.Counter`. + +For custom folders that hold components, add an [`@using`][2] directive to the parent component or to the app's `_Imports.razor` file. The following example makes components in the `AdminComponents` folder available: + +```razor +@using BlazorSample.AdminComponents +``` + +> [!NOTE] +> [`@using`][2] directives in the `_Imports.razor` file are only applied to Razor files (`.razor`), not C# files (`.cs`). + +Aliased [`using`](/dotnet/csharp/language-reference/keywords/using-directive) statements are supported. In the following example, the public `WeatherForecast` class of the `GridRendering` component is made available as `WeatherForecast` in a component elsewhere in the app: + +```razor +@using WeatherForecast = Components.Pages.GridRendering.WeatherForecast +``` + +Components can also be referenced using their fully qualified names, which doesn't require an [`@using`][2] directive. The following example directly references the `ProductDetail` component in the `AdminComponents/Pages` folder of the app: + +```razor + +``` + +The namespace of a component authored with Razor is based on the following (in priority order): + +* The [`@namespace`][8] directive in the Razor file's markup (for example, `@namespace BlazorSample.CustomNamespace`). +* The project's `RootNamespace` in the project file (for example, `BlazorSample`). +* The project namespace and the path from the project root to the component. For example, the framework resolves `{PROJECT NAMESPACE}/Components/Pages/Home.razor` with a project namespace of `BlazorSample` to the namespace `BlazorSample.Components.Pages` for the `Home` component. `{PROJECT NAMESPACE}` is the project namespace. Components follow C# name binding rules. For the `Home` component in this example, the components in scope are all of the components: + * In the same folder, `Components/Pages`. + * The components in the project's root that don't explicitly specify a different namespace. + +The following are **not** supported: + + + +* The [`global::`](/dotnet/csharp/language-reference/operators/namespace-alias-qualifier) qualification. +* Partially-qualified names. For example, you can't add `@using BlazorSample` to a component and then reference the `NavMenu` component in the app's `Components/Layout` folder (`Components/Layout/NavMenu.razor`) with ``. + +:::moniker-end + +:::moniker range="< aspnetcore-8.0" + A component's name must start with an uppercase character: Supported: `ProductDetail.razor` @@ -47,11 +110,11 @@ A component's name must start with an uppercase character: Common Blazor naming conventions used throughout the Blazor documentation include: -* Component file paths use Pascal case† and appear before showing component code examples. Paths indicate typical folder locations. For example, `Pages/ProductDetail.razor` indicates that the `ProductDetail` component has a file name of `ProductDetail.razor` and resides in the `Pages` folder of the app. +* File paths and file names use Pascal case† and appear before showing code examples. If a path is present, it indicates the typical folder location. For example, `Pages/ProductDetail.razor` indicates that the `ProductDetail` component has a file name of `ProductDetail.razor` and resides in the `Pages` folder of the app. * Component file paths for routable components match their URLs in kebab case‡ with hyphens appearing between words in a component's route template. For example, a `ProductDetail` component with a route template of `/product-detail` (`@page "/product-detail"`) is requested in a browser at the relative URL `/product-detail`. †Pascal case (upper camel case) is a naming convention without spaces and punctuation and with the first letter of each word capitalized, including the first word. -‡kebab case is a naming convention without spaces and punctuation that uses lowercase letters and dashes between words. +‡Kebab case is a naming convention without spaces and punctuation that uses lowercase letters and dashes between words. Components are ordinary [C# classes](/dotnet/csharp/programming-guide/classes-and-structs/classes) and can be placed anywhere within a project. Components that produce webpages usually reside in the `Pages` folder. Non-page components are frequently placed in the `Shared` folder or a custom folder added to the project. @@ -60,10 +123,10 @@ Typically, a component's namespace is derived from the app's root namespace and * The `Counter` component's namespace is `BlazorSample.Pages`. * The fully qualified type name of the component is `BlazorSample.Pages.Counter`. -For custom folders that hold components, add an [`@using`][2] directive to the parent component or to the app's `_Imports.razor` file. The following example makes components in the `Components` folder available: +For custom folders that hold components, add an [`@using`][2] directive to the parent component or to the app's `_Imports.razor` file. The following example makes components in the `AdminComponents` folder available: ```razor -@using BlazorSample.Components +@using BlazorSample.AdminComponents ``` > [!NOTE] @@ -85,7 +148,7 @@ The namespace of a component authored with Razor is based on the following (in p * The [`@namespace`][8] directive in the Razor file's markup (for example, `@namespace BlazorSample.CustomNamespace`). * The project's `RootNamespace` in the project file (for example, `BlazorSample`). -* The project name, taken from the project file's file name (`.csproj`), and the path from the project root to the component. For example, the framework resolves `{PROJECT ROOT}/Pages/Index.razor` with a project namespace of `BlazorSample` (`BlazorSample.csproj`) to the namespace `BlazorSample.Pages` for the `Index` component. `{PROJECT ROOT}` is the project root path. Components follow C# name binding rules. For the `Index` component in this example, the components in scope are all of the components: +* The project namespace and the path from the project root to the component. For example, the framework resolves `{PROJECT NAMESPACE}/Pages/Index.razor` with a project namespace of `BlazorSample` to the namespace `BlazorSample.Pages` for the `Index` component. `{PROJECT NAMESPACE}` is the project namespace. Components follow C# name binding rules. For the `Index` component in this example, the components in scope are all of the components: * In the same folder, `Pages`. * The components in the project's root that don't explicitly specify a different namespace. @@ -94,6 +157,8 @@ The following are **not** supported: * The [`global::`](/dotnet/csharp/language-reference/operators/namespace-alias-qualifier) qualification. * Partially-qualified names. For example, you can't add `@using BlazorSample` to a component and then reference the `NavMenu` component in the app's `Shared` folder (`Shared/NavMenu.razor`) with ``. +:::moniker-end + ### Partial class support Components are generated as [C# partial classes](/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods) and are authored using either of the following approaches: @@ -110,7 +175,7 @@ Components are generated as [C# partial classes](/dotnet/csharp/programming-guid The following example shows the default `Counter` component with an [`@code`][1] block in an app generated from a Blazor project template. Markup and C# code are in the same file. This is the most common approach taken in component authoring. -`Pages/Counter.razor`: +`Counter.razor`: :::moniker range=">= aspnetcore-7.0" @@ -138,7 +203,7 @@ The following example shows the default `Counter` component with an [`@code`][1] The following `Counter` component splits presentation HTML and Razor markup from the C# code using a code-behind file with a partial class. Splitting the markup from the C# code is favored by some organizations and developers to organize their component code to suit how they prefer to work. For example, the organization's UI expert can work on the presentation layer independently of another developer working on the component's C# logic. The approach is also useful when working with automatically-generated code or source generators. For more information, see [Partial Classes and Methods (C# Programming Guide)](/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods). -`Pages/CounterPartialClass.razor`: +`CounterPartialClass.razor`: :::moniker range=">= aspnetcore-7.0" @@ -164,9 +229,27 @@ The following `Counter` component splits presentation HTML and Razor markup from :::moniker-end -`Pages/CounterPartialClass.razor.cs`: +`CounterPartialClass.razor.cs`: -:::moniker range=">= aspnetcore-6.0" +:::moniker range=">= aspnetcore-8.0" + +```csharp +namespace BlazorSample.Components.Pages; + +public partial class CounterPartialClass +{ + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } +} +``` + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0 < aspnetcore-8.0" ```csharp namespace BlazorSample.Pages; @@ -222,6 +305,13 @@ using Microsoft.AspNetCore.Components.Web.Virtualization; using Microsoft.JSInterop; ``` +Typical namespaces also include the namespace of the app and the namespace corresponding to the app's `Components` folder: + +```csharp +using BlazorSample; +using BlazorSample.Components; +``` + :::moniker-end :::moniker range=">= aspnetcore-6.0 < aspnetcore-8.0" @@ -238,6 +328,13 @@ using Microsoft.AspNetCore.Components.Web.Virtualization; using Microsoft.JSInterop; ``` +Typical namespaces also include the namespace of the app and the namespace corresponding to the app's `Shared` folder: + +```csharp +using BlazorSample; +using BlazorSample.Shared; +``` + :::moniker-end :::moniker range="< aspnetcore-6.0" @@ -250,8 +347,6 @@ using Microsoft.AspNetCore.Components.Web; using Microsoft.JSInterop; ``` -:::moniker-end - Typical namespaces also include the namespace of the app and the namespace corresponding to the app's `Shared` folder: ```csharp @@ -259,13 +354,15 @@ using BlazorSample; using BlazorSample.Shared; ``` +:::moniker-end + ### Specify a base class The [`@inherits`][6] directive is used to specify a base class for a component. Unlike using [partial classes](#partial-class-support), which only split markup from C# logic, using a base class allows you to inherit C# code for use across a group of components that share the base class's properties and methods. Using base classes reduce code redundancy in apps and are useful when supplying base code from class libraries to multiple apps. For more information, see [Inheritance in C# and .NET](/dotnet/csharp/fundamentals/tutorials/inheritance). In the following example, the `BlazorRocksBase` base class derives from . -`Pages/BlazorRocks.razor`: +`BlazorRocks.razor`: :::moniker range=">= aspnetcore-7.0" @@ -321,9 +418,9 @@ In the following example, the `BlazorRocksBase` base class derives from specifying the route template. At runtime, the router searches for component classes with a and renders whichever component has a route template that matches the requested URL. -The following `HelloWorld` component uses a route template of `/hello-world`, and the rendered webpage for the component is reached at the relative URL `/hello-world`. Components that produce webpages usually reside in the `Pages` folder, but you can use any folder to hold components, including within nested folders. +The following `HelloWorld` component uses a route template of `/hello-world`, and the rendered webpage for the component is reached at the relative URL `/hello-world`. -`Pages/HelloWorld.razor`: +`HelloWorld.razor`: :::moniker range=">= aspnetcore-7.0" @@ -351,7 +448,7 @@ The following `HelloWorld` component uses a route template of `/hello-world`, an The preceding component loads in the browser at `/hello-world` regardless of whether or not you add the component to the app's UI navigation. Optionally, components can be added to the `NavMenu` component so that a link to the component appears in the app's UI-based navigation. -For the preceding `HelloWorld` component, you can add a `NavLink` component to the `NavMenu` component in the `Shared` folder. For more information, including descriptions of the `NavLink` and `NavMenu` components, see . +For the preceding `HelloWorld` component, you can add a `NavLink` component to the `NavMenu` component. For more information, including descriptions of the `NavLink` and `NavMenu` components, see . ### Markup @@ -368,7 +465,7 @@ Component members are used in rendering logic using C# expressions that start wi * `headingFontStyle` for the CSS property value `font-style` of the heading element. * `headingText` for the content of the heading element. -`Pages/Markup.razor`: +`Markup.razor`: :::moniker range=">= aspnetcore-7.0" @@ -411,7 +508,7 @@ Components can include other components by declaring them using HTML syntax. The Consider the following `Heading` component, which can be used by other components to display a heading. -`Shared/Heading.razor`: +`Heading.razor`: :::moniker range=">= aspnetcore-7.0" @@ -439,7 +536,7 @@ Consider the following `Heading` component, which can be used by other component The following markup in the `HeadingExample` component renders the preceding `Heading` component at the location where the `` tag appears. -`Pages/HeadingExample.razor`: +`HeadingExample.razor`: :::moniker range=">= aspnetcore-7.0" @@ -499,7 +596,7 @@ The `Heading` component example shown in this section doesn't have an [`@page`][ :::moniker-end -`Shared/ParameterChild.razor`: +`ParameterChild.razor`: :::moniker range=">= aspnetcore-7.0" @@ -533,7 +630,7 @@ The `Title` and `Body` component parameters of the `ParameterChild` component ar * The first `ParameterChild` component is rendered without supplying parameter arguments. * The second `ParameterChild` component receives values for `Title` and `Body` from the `ParameterParent` component, which uses an [explicit C# expression](xref:mvc/views/razor#explicit-razor-expressions) to set the values of the `PanelBody`'s properties. -`Pages/ParameterParent.razor`: +`ParameterParent.razor`: :::moniker range=">= aspnetcore-7.0" @@ -601,7 +698,7 @@ Throughout the documentation, code examples: * Use the `@` prefix with nonliterals, ***even when it's optional***. Example: `Count="@ct"`, where `ct` is a number-typed variable. `Count="ct"` is a valid stylistic approach, but the documentation and examples don't adopt the convention. * Always avoid `@` for literals, outside of Razor expressions. Example: `IsFixed="true"`. -`Pages/ParameterParent2.razor`: +`ParameterParent2.razor`: :::moniker range=">= aspnetcore-7.0" @@ -689,7 +786,7 @@ The code in the preceding example generates a *compiler error* when the app is b To support the assignment of a composed value, use a method, field, or property. The following example performs the concatenation of "`Set by `" and an object's property value in the C# method `GetTitle`: -`Pages/ParameterParent3.razor`: +`ParameterParent3.razor`: :::moniker range=">= aspnetcore-7.0" @@ -786,21 +883,21 @@ Don't use the [`init` accessor](/dotnet/csharp/language-reference/keywords/init) [`Tuples`](/dotnet/csharp/language-reference/builtin-types/value-tuples) ([API documentation](xref:System.Tuple)) are supported for component parameters and [`RenderFragment`](#child-content-render-fragments) types. The following component parameter example passes three values in a `Tuple`: -`Shared/RenderTupleChild.razor`: +`RenderTupleChild.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_Server/Shared/index/RenderTupleChild.razor"::: -`Pages/RenderTupleParent.razor`: +`RenderTupleParent.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_Server/Pages/index/RenderTupleParent.razor"::: [Named tuples](/dotnet/csharp/language-reference/builtin-types/value-tuples#tuple-field-names) are supported, as seen in the following example: -`Shared/RenderNamedTupleChild.razor`: +`RenderNamedTupleChild.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_Server/Shared/index/RenderNamedTupleChild.razor"::: -`Pages/RenderNamedTupleParent.razor`: +`RenderNamedTupleParent.razor`: :::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_Server/Pages/index/RenderNamedTupleParent.razor"::: @@ -824,7 +921,7 @@ Optional route parameters aren't supported, so two [`@page`][9] directives are a :::moniker-end -`Pages/RouteParameter.razor`: +`RouteParameter.razor`: :::moniker range=">= aspnetcore-7.0" @@ -858,7 +955,7 @@ Components can set the content of another component. The assigning component pro In the following example, the `RenderFragmentChild` component has a `ChildContent` component parameter that represents a segment of the UI to render as a . The position of `ChildContent` in the component's Razor markup is where the content is rendered in the final HTML output. -`Shared/RenderFragmentChild.razor`: +`RenderFragmentChild.razor`: :::moniker range=">= aspnetcore-7.0" @@ -891,7 +988,7 @@ In the following example, the `RenderFragmentChild` component has a `ChildConten The following `RenderFragmentParent` component provides content for rendering the `RenderFragmentChild` by placing the content inside the child component's opening and closing tags. -`Pages/RenderFragmentParent.razor`: +`RenderFragmentParent.razor`: :::moniker range=">= aspnetcore-7.0" @@ -989,7 +1086,7 @@ When the component is rendered, the field is populated with the component instan Consider the following `ReferenceChild` component that logs a message when its `ChildMethod` is called. -`Shared/ReferenceChild.razor`: +`ReferenceChild.razor`: :::moniker range=">= aspnetcore-7.0" @@ -1023,7 +1120,7 @@ To use a reference variable with an event handler, use a lambda expression or as The following lambda approach uses the preceding `ReferenceChild` component. -`Pages/ReferenceParent1.razor`: +`ReferenceParent1.razor`: :::moniker range=">= aspnetcore-7.0" @@ -1051,7 +1148,7 @@ The following lambda approach uses the preceding `ReferenceChild` component. The following delegate approach uses the preceding `ReferenceChild` component. -`Pages/ReferenceParent2.razor`: +`ReferenceParent2.razor`: :::moniker range=">= aspnetcore-7.0" @@ -1097,7 +1194,7 @@ HTML element attribute properties are conditionally set based on the .NET value. In the following example, `IsCompleted` determines if the `` element's `checked` property is set. -`Pages/ConditionalAttribute.razor`: +`ConditionalAttribute.razor`: :::moniker range=">= aspnetcore-7.0" @@ -1137,7 +1234,7 @@ Strings are normally rendered using DOM text nodes, which means that any markup The following example shows using the type to add a block of static HTML content to the rendered output of a component. -`Pages/MarkupStringExample.razor`: +`MarkupStringExample.razor`: :::moniker range=">= aspnetcore-7.0" @@ -1173,7 +1270,7 @@ Render fragments can be defined using Razor template syntax to define a UI snipp The following example illustrates how to specify and values and render templates directly in a component. Render fragments can also be passed as arguments to [templated components](xref:blazor/components/templated-components). -`Pages/RazorTemplate.razor`: +`RazorTemplate.razor`: :::moniker range=">= aspnetcore-7.0" diff --git a/aspnetcore/blazor/components/js-spa-frameworks.md b/aspnetcore/blazor/components/js-spa-frameworks.md index 971eeb97fd74..8ed649c40d07 100644 --- a/aspnetcore/blazor/components/js-spa-frameworks.md +++ b/aspnetcore/blazor/components/js-spa-frameworks.md @@ -20,7 +20,7 @@ Razor components can be dynamically-rendered from JavaScript (JS) for existing J The example in this section renders the following Razor component into a page via JS. -`Shared/Quote.razor`: +`Quote.razor`: ```razor
@@ -34,11 +34,7 @@ The example in this section renders the following Razor component into a page vi } ``` -In the `Program` file, add the namespace for the location of the component. The following example assumes that the `Quote` component is in the app's `Shared` folder, and the app's namespace is `BlazorSample`: - -```csharp -using BlazorSample.Shared; -``` +In the `Program` file, add the [namespace for the location of the component](xref:blazor/components/index#component-name-class-name-and-namespace). Call on the app's root component collection to register the a Razor component as a root component for JS rendering. @@ -68,7 +64,7 @@ The following example demonstrates the dynamic registration of the preceding `Qu :::moniker range="< aspnetcore-8.0" -* In a Blazor Server app, modify the call to in `Program.cs`: +* In a Blazor Server app, modify the call to in the `Program` file: ```csharp builder.Services.AddServerSideBlazor(options => @@ -162,7 +158,7 @@ Quote ©1988-1999 Satellite of Love LLC: [*Mystery Science Theater 3000*](ht The preceding example dynamically renders the root component when the `showQuote()` JS function is called. To render a root component into a container element when Blazor starts, use a [JavaScript initializer](xref:blazor/fundamentals/startup#javascript-initializers) to render the component, as the following example demonstrates. -The following example builds on the preceding example, using the `Quote` component, the root component registration in `Program.cs`, and the initialization of `jsComponentInitializers.js`. The `showQuote()` function (and the `script.js` file) aren't used. +The following example builds on the preceding example, using the `Quote` component, the root component registration in the `Program` file, and the initialization of `jsComponentInitializers.js`. The `showQuote()` function (and the `script.js` file) aren't used. In HTML, place the target container element, `quoteContainer2` for this example: @@ -247,7 +243,7 @@ builder.Services.AddRazorComponents() ``` > [!NOTE] -> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the server-side `Program` file. +> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Components.Pages;`) at the top of the server-side `Program` file. :::moniker-end @@ -255,7 +251,7 @@ builder.Services.AddRazorComponents() ### Blazor Server registration -To register a root component as a custom element in a Blazor Server app, modify the call to in `Program.cs`. The following example registers the `Counter` component with the custom HTML element `my-counter`: +To register a root component as a custom element in a Blazor Server app, modify the call to in the `Program` file. The following example registers the `Counter` component with the custom HTML element `my-counter`: ```csharp builder.Services.AddServerSideBlazor(options => @@ -265,7 +261,7 @@ builder.Services.AddServerSideBlazor(options => ``` > [!NOTE] -> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the `Program.cs` file. +> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Components.Pages;`) at the top of the `Program` file. :::moniker-end @@ -280,7 +276,7 @@ builder.RootComponents.RegisterCustomElement("my-counter"); ``` > [!NOTE] -> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) at the top of the client-side `Program` file. +> The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Components.Pages;`) at the top of the client-side `Program` file. ### Use the registered custom element @@ -300,7 +296,7 @@ Pass parameters to your Blazor component either as HTML attributes or as JavaScr The following `Counter` component uses an `IncrementAmount` parameter to set the increment amount of the **:::no-loc text="Click me":::** button. -`Pages/Counter.razor`: +`Counter.razor`: ```razor @page "/counter" @@ -355,7 +351,7 @@ Supported parameter types: Register a root component as a custom element: -* In a Blazor Server app, modify the call to in `Program.cs`: +* In a Blazor Server app, modify the call to in the `Program` file: ```csharp builder.Services.AddServerSideBlazor(options => @@ -365,16 +361,16 @@ Register a root component as a custom element: ``` > [!NOTE] - > The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) in the `Program.cs` file. + > The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Components.Pages;`) in the the `Program` file. -* In a Blazor WebAssembly app, call `RegisterAsCustomElement` on in `Program.cs`: +* In a Blazor WebAssembly app, call `RegisterAsCustomElement` on in the `Program` file: ```csharp builder.RootComponents.RegisterAsCustomElement("my-counter"); ``` > [!NOTE] - > The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Pages;`) in the `Program.cs` file. + > The preceding code example requires a namespace for the app's components (for example, `using BlazorSample.Components.Pages;`) in the the `Program` file. Include the following `