Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Blazor custom elements package (#377)
- Loading branch information
1 parent
de99be4
commit bd5cd1f
Showing
47 changed files
with
25,121 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 16 | ||
VisualStudioVersion = 16.0.30114.105 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{009CDD48-853D-48F0-A9CC-008C0F106F63}" | ||
EndProject | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Components.CustomElements", "src\Microsoft.AspNetCore.Components.CustomElements\Microsoft.AspNetCore.Components.CustomElements.csproj", "{98718095-4FE7-4698-9AED-B16B0E1AF59D}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{98718095-4FE7-4698-9AED-B16B0E1AF59D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{98718095-4FE7-4698-9AED-B16B0E1AF59D}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{98718095-4FE7-4698-9AED-B16B0E1AF59D}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{98718095-4FE7-4698-9AED-B16B0E1AF59D}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(NestedProjects) = preSolution | ||
{98718095-4FE7-4698-9AED-B16B0E1AF59D} = {009CDD48-853D-48F0-A9CC-008C0F106F63} | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
# Blazor Custom Elements | ||
|
||
This package provides a simple mechanism for using Blazor components as custom elements. This means you can easily render Blazor components dynamically from other SPA frameworks, such as Angular or React. | ||
|
||
## Running the Angular sample | ||
|
||
Clone this repo. Then, in a command prompt, execute: | ||
|
||
* `cd samples/BlazorAppProvidingCustomElements` | ||
* `dotnet watch` | ||
|
||
Leave that running, and open a second command prompt, and execute: | ||
|
||
* `cd samples/angular-app-with-blazor` | ||
* `npm install` | ||
* `npm start` | ||
|
||
Now when you browse to http://localhost:4200/, you'll see an Angular application that dynamically renders Blazor WebAssembly components, passing parameters to them. | ||
|
||
## Running the React sample | ||
|
||
Clone this repo. Then, in a command prompt, execute: | ||
|
||
* `cd samples/BlazorAppProvidingCustomElements` | ||
* `dotnet watch` | ||
|
||
Leave that running, and open a second command prompt, and execute: | ||
|
||
* `cd samples/react-app-with-blazor` | ||
* `yarn install` | ||
* `yarn start` | ||
|
||
Now when you browse to http://localhost:3000/, you'll see a React application that dynamically renders Blazor WebAssembly components, passing parameters to them. | ||
|
||
## Adding this to your own project | ||
|
||
1. Start with or create a Blazor WebAssembly or Blazor Server project that contains your Blazor components | ||
2. Install the NuGet package `Microsoft.AspNetCore.Components.CustomElements` | ||
3. In your Blazor application startup configuration, remove any normal Blazor root components, and instead register components as custom elements. See [Example for Blazor WebAssembly](#webassembly-example) or [Example for Blazor Server](#server-example). | ||
4. Configure your external SPA framework application to serve the Blazor framework files and render your Blazor custom elements. For example, see [Configuring Angular](#configuring-angular) or [Configuring React](#configuring-react). Similar techniques will work with other SPA frameworks. | ||
|
||
### WebAssembly example | ||
|
||
For Blazor WebAssembly, remove lines like this from `Program.cs`: | ||
|
||
```cs | ||
builder.RootComponents.Add<App>("#root"); | ||
``` | ||
|
||
... and add lines like the following instead: | ||
|
||
```cs | ||
builder.RootComponents.RegisterAsCustomElement<Counter>("my-blazor-counter"); | ||
builder.RootComponents.RegisterAsCustomElement<ProductGrid>("product-grid"); | ||
``` | ||
|
||
### Server example | ||
|
||
For Blazor Server, in `Program.cs` or `Startup.cs`, change the call to `AddServerSideBlazor` to pass an `options` callback like the following: | ||
|
||
```cs | ||
builder.Services.AddServerSideBlazor(options => | ||
{ | ||
options.RootComponents.RegisterAsCustomElement<Counter>("my-blazor-counter"); | ||
options.RootComponents.RegisterAsCustomElement<ProductGrid>("product-grid"); | ||
}); | ||
``` | ||
|
||
### Configuring Angular | ||
|
||
1. In your Angular `index.html`, add the following at the end of `<body>`: | ||
|
||
```html | ||
<script src="_content/Microsoft.AspNetCore.Components.CustomElements/BlazorCustomElements.js"></script> | ||
<script src="_framework/blazor.webassembly.js"></script> | ||
``` | ||
|
||
Note that the tag for `BlazorCustomElements.js` is only needed temporarily. This step will be removed in a future update. | ||
|
||
2. Run the application now and see that the browser gets a 404 error for those two JavaScript files. To fix this, [configure Angular CLI to proxy unmatches requests to the ASP.NET Core development server](https://angular.io/guide/build#proxying-to-a-backend-server). Of course, you also need to be running your ASP.NET Core development server at the same time for this to work. | ||
|
||
3. In any of your Angular components, render the custom elements corresponding to your Blazor components. For example, add to a `template` markup like the following: | ||
|
||
```html | ||
<my-blazor-counter [attr.title]="counter.title"></my-blazor-counter> | ||
``` | ||
|
||
This assumes that your component declares a parameter like the following: | ||
|
||
```cs | ||
[Parameter] public string Title { get; set; } | ||
``` | ||
|
||
If you have parameters that are complex-typed objects, you can use Angular's property-setting syntax as follows: | ||
|
||
```html | ||
<my-blazor-counter [someComplexObject]="someJsObject"></my-blazor-counter> | ||
``` | ||
|
||
This will cause `someJsObject` to be JSON-serialized and supplied as a Blazor component parameter called `SomeComplexObject`. | ||
|
||
4. If you get a compiler error saying that your custom element is "not a known element", [add `CUSTOM_ELEMENTS_SCHEMA` to your Angular component or module](https://stackoverflow.com/a/40407697). | ||
|
||
### Configuring React | ||
|
||
1. In your React `index.html`, add the following at the end of `<body>`: | ||
|
||
```html | ||
<script src="_content/Microsoft.AspNetCore.Components.CustomElements/BlazorCustomElements.js"></script> | ||
<script src="_framework/blazor.webassembly.js"></script> | ||
``` | ||
|
||
Note that the tag for `BlazorCustomElements.js` is only needed temporarily. This step will be removed in a future update. | ||
|
||
2. Run the application now and see that the browser gets a 404 error for those two JavaScript files. To fix this, [configure React's development server to proxy unmatches requests to the ASP.NET Core development server](https://create-react-app.dev/docs/proxying-api-requests-in-development/). Of course, you also need to be running your ASP.NET Core development server at the same time for this to work. | ||
|
||
3. In any of your React components, render the custom elements corresponding to your Blazor components. For example, have a React component render output include: | ||
|
||
```html | ||
<my-blazor-counter title={title} increment-amount={incrementAmount}></my-blazor-counter> | ||
``` | ||
|
||
Whenever you edit your React component source code, you'll see it update automatically in the browser without losing the state within your Blazor component. The two hot reload systems can coexist and cooperate. | ||
|
||
### Publishing your combined application | ||
|
||
The easiest way to have an application with both .NET parts and a 3rd-party SPA framework is to use the ASP.NET Core project templates [for Angular](https://docs.microsoft.com/aspnet/core/client-side/spa/angular) or [for React](https://docs.microsoft.com/aspnet/core/client-side/spa/react). This will automatically gather the files required for the combined application during publishing. | ||
|
||
If you're not using one of those project templates, you'll need to publish both the .NET and JavaScript parts separately and manually combine the files into a single deployable set. | ||
|
||
## Passing parameters | ||
|
||
You can pass parameters to your Blazor component either as HTML attributes or as JavaScript properties on the DOM element. | ||
|
||
For example, if your component declares a parameters like the following: | ||
|
||
```cs | ||
[Parameter] public int IncrementAmount { get; set; } | ||
``` | ||
|
||
... then you can pass a value as an HTML attribute follows: | ||
|
||
```html | ||
<my-blazor-counter increment-amount="123"></my-blazor-counter> | ||
``` | ||
|
||
Notice that the attribute name is kebab-case (i.e., `increment-amount`, not `IncrementAmount`). | ||
|
||
Alternatively, you can set it as a JavaScript property on the element object: | ||
|
||
```js | ||
const elem = document.querySelector("my-blazor-counter"); | ||
elem.incrementAmount = 123; | ||
``` | ||
|
||
Notice that the property name is camelCase (i.e., `incrementAmount`, not `IncrementAmount`). | ||
|
||
You can update parameter values at any time using either attribute or property syntax. | ||
|
||
### Supported parameter types | ||
|
||
* Using JavaScript property syntax, you can pass objects of any JSON-serializable type | ||
* Using HTML attributes, you are limited to passing objects of string, boolean, or numerical types |
17 changes: 17 additions & 0 deletions
17
...Elements/samples/BlazorAppProvidingCustomElements/BlazorAppProvidingCustomElements.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.0-rc.1.21381.3" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.0-rc.1.21381.3" PrivateAssets="all" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Components.CustomElements\Microsoft.AspNetCore.Components.CustomElements.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
18 changes: 18 additions & 0 deletions
18
src/BlazorCustomElements/samples/BlazorAppProvidingCustomElements/Counter.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<h1>@Title</h1> | ||
|
||
<p role="status">Current count: @currentCount</p> | ||
<p>Increment amount: @IncrementAmount</p> | ||
|
||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button> | ||
|
||
@code { | ||
private int currentCount = 0; | ||
|
||
[Parameter] public string Title { get; set; } = "Blazor Counter"; | ||
[Parameter] public int? IncrementAmount { get; set; } | ||
|
||
private void IncrementCount() | ||
{ | ||
currentCount += IncrementAmount.GetValueOrDefault(1); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/BlazorCustomElements/samples/BlazorAppProvidingCustomElements/Counter.razor.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
button { | ||
font-weight: bold; | ||
background-color: #7b31b8; | ||
color: white; | ||
border-radius: 4px; | ||
padding: 4px 12px; | ||
border: none; | ||
} | ||
|
||
button:hover { | ||
background-color: #9654cc; | ||
cursor: pointer; | ||
} | ||
|
||
button:active { | ||
background-color: #b174e4; | ||
} |
11 changes: 11 additions & 0 deletions
11
src/BlazorCustomElements/samples/BlazorAppProvidingCustomElements/Program.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using Microsoft.AspNetCore.Components.Web; | ||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; | ||
using BlazorAppProvidingCustomElements; | ||
|
||
var builder = WebAssemblyHostBuilder.CreateDefault(args); | ||
|
||
builder.RootComponents.RegisterAsCustomElement<Counter>("my-blazor-counter"); | ||
|
||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); | ||
|
||
await builder.Build().RunAsync(); |
9 changes: 9 additions & 0 deletions
9
src/BlazorCustomElements/samples/BlazorAppProvidingCustomElements/_Imports.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
@using System.Net.Http | ||
@using System.Net.Http.Json | ||
@using Microsoft.AspNetCore.Components.Forms | ||
@using Microsoft.AspNetCore.Components.Routing | ||
@using Microsoft.AspNetCore.Components.Web | ||
@using Microsoft.AspNetCore.Components.Web.Virtualization | ||
@using Microsoft.AspNetCore.Components.WebAssembly.Http | ||
@using Microsoft.JSInterop | ||
@using BlazorAppProvidingCustomElements |
7 changes: 7 additions & 0 deletions
7
src/BlazorCustomElements/samples/BlazorAppProvidingCustomElements/wwwroot/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<html> | ||
<body> | ||
<h1>Don't visit this page directly.</h1> | ||
<p>This project exists to provide custom elements to other projects.</p> | ||
<p>See README.md for instructions on running the custom element samples.</p> | ||
</body> | ||
</html> |
17 changes: 17 additions & 0 deletions
17
src/BlazorCustomElements/samples/angular-app-with-blazor/.browserslistrc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below. | ||
# For additional information regarding the format and rule options, please see: | ||
# https://github.com/browserslist/browserslist#queries | ||
|
||
# For the full list of supported browsers by the Angular framework, please see: | ||
# https://angular.io/guide/browser-support | ||
|
||
# You can see what browsers were selected by your queries by running: | ||
# npx browserslist | ||
|
||
last 1 Chrome version | ||
last 1 Firefox version | ||
last 2 Edge major versions | ||
last 2 Safari major versions | ||
last 2 iOS major versions | ||
Firefox ESR | ||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. |
45 changes: 45 additions & 0 deletions
45
src/BlazorCustomElements/samples/angular-app-with-blazor/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# See http://help.github.com/ignore-files/ for more about ignoring files. | ||
|
||
# compiled output | ||
/dist | ||
/tmp | ||
/out-tsc | ||
# Only exists if Bazel was run | ||
/bazel-out | ||
|
||
# dependencies | ||
/node_modules | ||
|
||
# profiling files | ||
chrome-profiler-events*.json | ||
|
||
# IDEs and editors | ||
/.idea | ||
.project | ||
.classpath | ||
.c9/ | ||
*.launch | ||
.settings/ | ||
*.sublime-workspace | ||
|
||
# IDE - VSCode | ||
.vscode/* | ||
!.vscode/settings.json | ||
!.vscode/tasks.json | ||
!.vscode/launch.json | ||
!.vscode/extensions.json | ||
.history/* | ||
|
||
# misc | ||
/.sass-cache | ||
/connect.lock | ||
/coverage | ||
/libpeerconnection.log | ||
npm-debug.log | ||
yarn-error.log | ||
testem.log | ||
/typings | ||
|
||
# System Files | ||
.DS_Store | ||
Thumbs.db |
Oops, something went wrong.